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 2015/10/12 19:15:51 UTC

[1/4] jena git commit: Rename to have 'Duration' in method name

Repository: jena
Updated Branches:
  refs/heads/master 2e18b8cdc -> d3180b5e7


Rename to have 'Duration' in method name


Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/b111837a
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/b111837a
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/b111837a

Branch: refs/heads/master
Commit: b111837a8a5375de6a1ea2210b2a3f2cf726b6aa
Parents: 2e18b8c
Author: Andy Seaborne <an...@apache.org>
Authored: Mon Oct 12 16:54:26 2015 +0100
Committer: Andy Seaborne <an...@apache.org>
Committed: Mon Oct 12 16:54:26 2015 +0100

----------------------------------------------------------------------
 .../main/java/org/apache/jena/sparql/expr/NodeValue.java    | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jena/blob/b111837a/jena-arq/src/main/java/org/apache/jena/sparql/expr/NodeValue.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/expr/NodeValue.java b/jena-arq/src/main/java/org/apache/jena/sparql/expr/NodeValue.java
index b83e3ba..ebb6621 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/expr/NodeValue.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/expr/NodeValue.java
@@ -914,7 +914,12 @@ public abstract class NodeValue extends ExprNode
     public boolean isTime()         { return false ; }
     public boolean isDuration()     { return false ; }
 
-    public boolean isYearMonth()
+    @Deprecated
+    public boolean isYearMonth() {
+        return isYearMonthDuration() ;
+    }
+    
+    public boolean isYearMonthDuration()
     {
         if ( ! isDuration() ) return false ;
         Duration dur = getDuration() ;
@@ -922,7 +927,7 @@ public abstract class NodeValue extends ExprNode
                ! dur.isSet(DAYS) && ! dur.isSet(HOURS) && ! dur.isSet(MINUTES) && ! dur.isSet(SECONDS) ;
     }
 
-    boolean isDayTime()
+    public boolean isDayTimeDuration()
     {
         if ( ! isDuration() ) return false ;
         Duration dur = getDuration() ;


[3/4] jena git commit: JENA-1047 : Rewrite casting to XSD datatypes.

Posted by an...@apache.org.
JENA-1047 : Rewrite casting to XSD datatypes.

Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/5156ba64
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/5156ba64
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/5156ba64

Branch: refs/heads/master
Commit: 5156ba64fbbc02765f9dda27154124f4f93d555e
Parents: 7aa9af5
Author: Andy Seaborne <an...@apache.org>
Authored: Mon Oct 12 17:46:39 2015 +0100
Committer: Andy Seaborne <an...@apache.org>
Committed: Mon Oct 12 17:46:39 2015 +0100

----------------------------------------------------------------------
 .../jena/sparql/expr/nodevalue/XSDFuncOp.java   |   8 +-
 .../apache/jena/sparql/function/CastXSD.java    | 135 --------
 .../apache/jena/sparql/function/CastXSD2.java   | 317 +++++++++++++++++++
 .../jena/sparql/function/CastXSD_Boolean.java   |  82 -----
 .../jena/sparql/function/CastXSD_DateTime.java  |  54 ----
 .../jena/sparql/function/CastXSD_Numeric.java   |  64 ----
 .../jena/sparql/function/StandardFunctions.java |  43 ++-
 .../org/apache/jena/sparql/expr/TS_Expr.java    |   1 +
 .../apache/jena/sparql/expr/TestCastXSD.java    | 136 ++++++++
 9 files changed, 480 insertions(+), 360 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jena/blob/5156ba64/jena-arq/src/main/java/org/apache/jena/sparql/expr/nodevalue/XSDFuncOp.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/expr/nodevalue/XSDFuncOp.java b/jena-arq/src/main/java/org/apache/jena/sparql/expr/nodevalue/XSDFuncOp.java
index 439948a..57a2497 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/expr/nodevalue/XSDFuncOp.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/expr/nodevalue/XSDFuncOp.java
@@ -1071,7 +1071,13 @@ public class XSDFuncOp
      */
     
     public static NodeValue dateTimeCast(NodeValue nv, XSDDatatype xsd) {
-        // http://www.w3.org/TR/xpath-functions/#casting-to-datetimes
+        if ( nv.isString() ) {
+            String s = nv.getString() ;
+            if ( ! xsd.isValid(s) )
+                throw new ExprEvalTypeException("Invalid lexical form: '"+s+"' for "+xsd.getURI()) ;
+            return NodeValue.makeNode(s, xsd) ;
+        }
+        
         if ( !nv.hasDateTime() )
             throw new ExprEvalTypeException("Not a date/time type: " + nv) ;
 

http://git-wip-us.apache.org/repos/asf/jena/blob/5156ba64/jena-arq/src/main/java/org/apache/jena/sparql/function/CastXSD.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/function/CastXSD.java b/jena-arq/src/main/java/org/apache/jena/sparql/function/CastXSD.java
deleted file mode 100644
index acec663..0000000
--- a/jena-arq/src/main/java/org/apache/jena/sparql/function/CastXSD.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * 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 org.apache.jena.sparql.function;
-
-import org.apache.jena.datatypes.xsd.XSDDatatype ;
-import org.apache.jena.datatypes.xsd.impl.XSDAbstractDateTimeType ;
-import org.apache.jena.datatypes.xsd.impl.XSDBaseNumericType ;
-import org.apache.jena.graph.Node ;
-import org.apache.jena.sparql.expr.ExprEvalException ;
-import org.apache.jena.sparql.expr.NodeValue ;
-
-/** General casting of XSD datatypes. 
- * @see CastXSD_DateTime 
- * @see CastXSD_Numeric 
- * @see CastXSD_Boolean 
- */
-public class CastXSD implements FunctionFactory
-{
-    protected final XSDDatatype castType ;
-    
-    public CastXSD(XSDDatatype dt)
-    {
-        this.castType = dt ; 
-    }
-    
-    @Override
-    public Function create(String uri)
-    {        
-        return new Instance(castType) ;
-    }
-
-    protected static class Instance extends FunctionBase1 
-    {
-        XSDDatatype castType ;
-        Instance(XSDDatatype dt) {this.castType = dt ;  }
-
-        @Override
-        public NodeValue exec(NodeValue v)
-        {
-            // http://www.w3.org/TR/xpath-functions/#casting
-            String s = null ;
-            Node n = v.asNode() ;
-
-            if ( n.isBlank() )
-                throw new ExprEvalException("CastXSD: Can't cast blank nodes: "+v) ;
-
-            if ( n.isURI() )
-            {
-                if ( castType.equals(XSDDatatype.XSDstring) )
-                    s = n.getURI() ;
-                else
-                    throw new ExprEvalException("CastXSD: Can't cast node: "+v+" to "+castType.getURI()) ;
-            }
-            else if ( n.isLiteral() ) 
-                // What if there is a lang tag?
-                s = n.getLiteralLexicalForm() ;
-            else
-                throw new ExprEvalException("CastXSD: Can't cast node: "+v+ "(not a literal, not URI to string)") ;
-
-            if ( s == null && v.isString() ) 
-                s = v.getString() ;
-
-            if ( s == null )
-                throw new ExprEvalException("CastXSD: Can't cast: "+v+ "(has no string appearance)") ;
-            
-            //        // Special case - non-normalised xsd:booleans use 0 and 1.
-            //        if ( v.isBoolean() )
-            //        {
-            //            if ( s.equals("0") ) s = "false" ;
-            //            if ( s.equals("1") ) s = "true" ;
-            //        }
-
-            NodeValue r = cast(s, v, castType) ;
-            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.
-            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+"'") ;
-            }
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/jena/blob/5156ba64/jena-arq/src/main/java/org/apache/jena/sparql/function/CastXSD2.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/function/CastXSD2.java b/jena-arq/src/main/java/org/apache/jena/sparql/function/CastXSD2.java
new file mode 100644
index 0000000..6d742b3
--- /dev/null
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/function/CastXSD2.java
@@ -0,0 +1,317 @@
+/**
+ * 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 org.apache.jena.sparql.function;
+
+import java.math.BigDecimal ;
+import java.math.BigInteger ;
+import java.util.Objects ;
+
+import javax.xml.datatype.DatatypeConstants ;
+import javax.xml.datatype.Duration ;
+
+import org.apache.jena.datatypes.xsd.XSDDatatype ;
+import org.apache.jena.datatypes.xsd.impl.XSDAbstractDateTimeType ;
+import org.apache.jena.datatypes.xsd.impl.XSDBaseNumericType ;
+import org.apache.jena.graph.Node ;
+import org.apache.jena.sparql.expr.ExprEvalException ;
+import org.apache.jena.sparql.expr.ExprEvalTypeException ;
+import org.apache.jena.sparql.expr.ExprException ;
+import org.apache.jena.sparql.expr.NodeValue ;
+import org.apache.jena.sparql.expr.nodevalue.XSDFuncOp ;
+
+public class CastXSD2 extends FunctionBase1 implements FunctionFactory {
+    
+    protected final XSDDatatype castType ;
+    
+    public CastXSD2(XSDDatatype dt)
+    {
+        this.castType = dt ; 
+    }
+    
+    @Override
+    public Function create(String uri)
+    {        
+        return this ;
+    }
+    
+    @Override
+    public NodeValue exec(NodeValue v)
+    {
+        return cast(v, castType) ;
+    }
+
+    
+    private static boolean isTemporalDatatype(XSDDatatype datatype) {
+        return 
+            datatype.equals(XSDDatatype.XSDdateTime) ||
+            datatype.equals(XSDDatatype.XSDtime) ||
+            datatype.equals(XSDDatatype.XSDdate) ||
+            datatype.equals(XSDDatatype.XSDgYear) ||
+            datatype.equals(XSDDatatype.XSDgYearMonth) ||
+            datatype.equals(XSDDatatype.XSDgMonth) ||
+            datatype.equals(XSDDatatype.XSDgMonthDay) ||
+            datatype.equals(XSDDatatype.XSDgDay) ;
+    }
+    
+    private static boolean isDurationDatatype(XSDDatatype datatype) {
+        return 
+            datatype.equals(XSDDatatype.XSDduration) || 
+            datatype.equals(XSDDatatype.XSDyearMonthDuration) ||
+            datatype.equals(XSDDatatype.XSDdayTimeDuration ) ;
+    }
+    
+    /** Cast a NodeValue to an XSD datatype.
+     * This includes "by value" so 1e0 (an xsd:double) casts to 1 (an xsd:intger) 
+     * @param nv
+     * @param castType
+     * @return NodeValue
+     * @throws ExprEvalException
+     */
+    public static NodeValue cast(NodeValue nv, XSDDatatype castType) {
+        // http://www.w3.org/TR/xpath-functions/#casting
+        Node n = nv.asNode() ;
+    
+        if ( n.isBlank() )
+            throw exception("Can't cast blank nodes: "+nv) ;
+    
+        if ( n.isURI() ) {
+            if ( castType.equals(XSDDatatype.XSDstring) )
+                return cast$(n.getURI(), castType) ;
+            else
+                throw exception("Can't cast URIs to "+castType.getURI()) ;
+        }
+    
+        if ( ! n.isLiteral() )
+            throw exception("Can't cast (not a literal, nor URI to string) "+nv+" : "+castType.getURI()) ;
+
+        // It's a literal.
+        
+        // Cast to self but may be an  invalid lexical form.
+        if ( Objects.equals(nv.getNode().getLiteralDatatype(), castType) ) {
+            String lex = nv.getNode().getLiteralLexicalForm() ;
+            if ( castType.isValid(lex) )
+                return nv ;
+            throw exception("Invalid lexical form for "+castType.getURI()) ;  
+        }
+
+        
+        // Many casts can be done by testing the lexical is valid for the datatype.
+        // But some cases need to consider values.
+        //  e.g. boolean -> numeric , double -> integer (doubles have "e" in them)
+        
+        // To a temporal
+        if ( isTemporalDatatype(castType) ) {
+            return XSDFuncOp.dateTimeCast(nv, castType) ;
+        }
+        
+        if ( isDurationDatatype(castType) ) {
+            // Duration cast.
+            // yearMonthDuration and TT is xs:dayTimeDuration -> 0.0S
+            // xs:dayTimeDuration and TT is yearMonthDuration -> P0M
+            
+            if ( nv.isDuration() ) {
+                Duration d = nv.getDuration() ;
+                if ( castType.equals(XSDDatatype.XSDyearMonthDuration) ) {
+                    
+                    // Include xsd:duration only covering year-month.
+                    if ( nv.isDayTimeDuration() )
+                        return NodeValue.makeNode("P0M", castType) ;
+                    
+                    Duration d2 =  NodeValue.xmlDatatypeFactory.newDuration
+                        (d.getSign()>=0,
+                            (BigInteger)d.getField(DatatypeConstants.YEARS), (BigInteger)d.getField(DatatypeConstants.MONTHS), null,
+                        null, null, null) ;
+                    return NodeValue.makeNode(d2.toString(), castType) ;
+                }
+                if ( castType.equals(XSDDatatype.XSDdayTimeDuration) ) {
+                    if ( nv.isYearMonthDuration() )
+                        return NodeValue.makeNode("PT0S", castType) ;
+                    Duration d2 =  NodeValue.xmlDatatypeFactory.newDuration
+                        
+                        (d.getSign()>=0,
+                        null, null, (BigInteger)d.getField(DatatypeConstants.DAYS),
+                        (BigInteger)d.getField(DatatypeConstants.HOURS), (BigInteger)d.getField(DatatypeConstants.MINUTES), (BigDecimal)d.getField(DatatypeConstants.SECONDS)) ;
+                    // return NodeValue.makeDuration(d2) ;
+                    return NodeValue.makeNode(d2.toString(), castType) ;
+                }
+            }
+        }
+
+        // From number, can consider value.
+        if ( nv.isNumber() ) {
+            if ( castType.equals(XSDDatatype.XSDdecimal) ) {   
+                // Number to decimal.
+                if ( isDouble(nv) || isFloat(nv) ) {
+                    // FP to decimal.
+                    double d = nv.getDouble() ;
+                    if ( Double.isNaN(d) )
+                        throw exception("Can't cast NaN to xsd:decimal") ;
+                    if ( Double.isInfinite(d) )
+                        throw exception("Can't cast Inf or -Inf to xsd:decimal") ;
+                    // BigDecimal.valueOf(d) can lead to trailing zeros
+                    // BigDecimal.valueOf(d) goes via strings.
+                    String lex = doubleToDecimalString(d) ;
+                    return NodeValue.makeDecimal(lex) ;
+                }
+                // Integer, or derived type -> decimal. 
+                return castByLex(nv, castType) ;
+            }
+            if ( XSDFuncOp.isIntegerType(castType) ) {
+                // Number to integer
+                if ( isDouble(nv) || isFloat(nv) ) {
+                    // FP to integer
+                    double d = nv.getDouble() ;
+                    boolean isIntegerValue = ( Math.rint(d) == d ) ;
+                    if ( isIntegerValue ) {
+                        String lex = doubleIntegerToString(d) ;
+                        if ( lex != null )
+                            return castByLex(lex, castType) ;
+                    }
+                    throw exception(nv, castType) ;
+                } else if ( isDecimal(nv) ) {
+                    // Decimal to integer
+                    BigDecimal bd = nv.getDecimal() ;
+                    try {
+                        // Exception on fraction. 
+                        BigInteger bi = bd.toBigIntegerExact() ;
+                        return castByLex(bi.toString(), castType) ;
+                    } catch (ArithmeticException ex) {
+                        throw new ExprEvalException("CastXSD: Not a valid cast: '"+nv+"'") ;
+                    }
+                } else {
+                    // Integer derived type -> integer derived type.
+                    return castByLex(nv, castType) ;
+                }
+            }
+        }
+    
+        // Boolean -> xsd:
+        if ( nv.isBoolean() ) { 
+            boolean b = nv.getBoolean() ;
+            // Boolean to boolean covered above.
+            String lex ;
+            if ( XSDDatatype.XSDfloat.equals(castType) || XSDDatatype.XSDdouble.equals(castType) )
+                return cast$( ( b ? "1.0E0" : "0.0E0" ) , castType) ;
+            else if ( XSDDatatype.XSDdecimal.equals(castType) )
+                return cast$( ( b ? "1.0" : "0.0" ) , castType) ;
+            else if ( XSDFuncOp.isIntegerType(castType)) 
+                return cast$(  ( b ? "1" : "0" ) , castType ) ;
+            else if ( XSDDatatype.XSDstring.equals(castType) ) 
+                return cast$( nv.getNode().getLiteralLexicalForm(), castType ) ;
+            throw exception("Can't cast xsd:boolean to "+castType) ;
+        }
+
+        // Try by lexical
+        return castByLex(nv, castType) ;
+    }
+
+    /** Presentation form of an XSD datatype URI */
+    private static String xsdName(String datatype) {
+        return datatype.replaceAll(XSDDatatype.XSD+"#", "xsd:") ;
+    }
+
+    /** Test to see if a NodeValue is a valid double value and is of datatype xsd:double. */ 
+    private static boolean isDouble(NodeValue nv) {
+        return nv.isDouble() && nv.getDatatypeURI().equals(XSDDatatype.XSDdouble.getURI()) ;
+    }
+
+    /** Test to see if a NodeValue is a valid float value and is of datatype float. */ 
+    private static boolean isFloat(NodeValue nv) {
+        return nv.isFloat() && nv.getDatatypeURI().equals(XSDDatatype.XSDfloat.getURI()) ;
+    }
+
+    /** Test to see if a NodeValue is a valid decimal value and is of datatype decimal. */ 
+    private static boolean isDecimal(NodeValue nv) {
+        return nv.isDecimal() && nv.getDatatypeURI().equals(XSDDatatype.XSDdecimal.getURI()) ;
+    }
+
+    /** Test to see if a NodeValue is a valid numeric value. */ 
+    private static boolean isNumeric(NodeValue nv) {
+        return nv.isNumber() ;
+    }
+
+    private static ExprException exception(NodeValue nv, XSDDatatype dt) {
+        return exception("Invalid cast: "+nv+" -> "+xsdName(dt.getURI())) ;
+    }
+    
+    private static ExprException exception(String msg) {
+        return new ExprEvalTypeException(msg) ;
+    }
+
+    // Cast by lexical form with checking.
+    private static NodeValue castByLex(NodeValue nv, XSDDatatype castType) {
+        String lex = nv.getNode().getLiteralLexicalForm() ;
+        return castByLex(lex, castType) ;
+    }
+
+    // Cast by lexical form with checking.
+    private static NodeValue castByLex(String lex, XSDDatatype castType) {
+        if ( ! castType.isValid(lex) )
+            throw exception("Invalid lexical form: '"+lex+"' for "+castType.getURI()) ;
+        if ( castType instanceof XSDBaseNumericType || 
+            castType.equals(XSDDatatype.XSDfloat) ||
+            castType.equals(XSDDatatype.XSDdouble) ||
+            castType.equals(XSDDatatype.XSDboolean) ||
+            castType instanceof XSDAbstractDateTimeType )   // Includes durations, and Gregorian
+        {
+            // More helpful error message.
+            if ( lex.startsWith(" ") || lex.endsWith(" ") )
+                throw exception("Not a valid literal form (has whitespace): '"+lex+"'") ;
+        }
+        return NodeValue.makeNode(lex, castType) ;
+
+    }
+
+    // Known to work casts.  No checking.
+    private static NodeValue cast$(String lex, XSDDatatype castType) {
+        return NodeValue.makeNode(lex, castType) ;
+    }
+
+    // Return the integer lexical form for a double, where the double is known to be integer valued.
+    private static String doubleIntegerToString(double d) {
+        // Fast path
+        long x = Math.round(d) ;
+        if ( x != Long.MAX_VALUE && x != Long.MIN_VALUE )
+            return  Long.toString(x) ;
+
+        String lex = BigDecimal.valueOf(d).toPlainString() ;
+        int i = lex.indexOf('.') ;
+        if ( i >= 0 )
+            // Adds .0 for some (small) doubles. 
+            lex = lex.substring(0, i) ;
+        return lex;
+    }
+
+    // Return the decimal lexical form for a double value.
+    // Java big decimal allows "E" forms, XSD does not.
+    private static String doubleToDecimalString(double d) {
+        // BigDecimal.valueOf(d) can lead to trailing zeros.
+        String lex = BigDecimal.valueOf(d).toPlainString() ;
+        // Clean the string. 
+        int i = lex.indexOf('.') ;
+        if ( i < 0 )
+            return lex ;
+        // Often one or two
+        while(lex.endsWith("00"))
+            lex = lex.substring(0,  lex.length()-2) ;
+        while(lex.endsWith("0"))
+            lex = lex.substring(0,  lex.length()-1) ;
+        return lex ;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jena/blob/5156ba64/jena-arq/src/main/java/org/apache/jena/sparql/function/CastXSD_Boolean.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/function/CastXSD_Boolean.java b/jena-arq/src/main/java/org/apache/jena/sparql/function/CastXSD_Boolean.java
deleted file mode 100644
index 156c201..0000000
--- a/jena-arq/src/main/java/org/apache/jena/sparql/function/CastXSD_Boolean.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * 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 org.apache.jena.sparql.function;
-
-import java.math.BigDecimal ;
-import java.math.BigInteger ;
-
-import org.apache.jena.datatypes.xsd.XSDDatatype ;
-import org.apache.jena.sparql.expr.NodeValue ;
-
-public class CastXSD_Boolean extends CastXSD
-{
-    public CastXSD_Boolean(XSDDatatype dt)
-    {
-        super(dt) ;
-    }
-    
-    @Override
-    public Function create(String uri)
-    {        
-        return new Instance(castType) ;
-    }
-
-
-    protected static class Instance extends CastXSD.Instance 
-    {
-        Instance(XSDDatatype dt)
-        {
-            super(dt) ;
-        }
-
-        @Override
-        protected NodeValue cast(String s, NodeValue nv, XSDDatatype castType)
-        {
-            if ( nv.isNumber() )
-            {
-                if ( nv.isFloat() || nv.isDouble() )
-                {
-                    // 0, +0, -0, 0.0, 0.0E0 or NaN, then TV is false.
-                    // else true.
-                    double d = ( nv.isDouble() ? nv.getDouble() : nv.getFloat() ) ;
-                    if ( d == 0.0e0 || Double.isNaN(d) )
-                        return NodeValue.FALSE ;
-                    return NodeValue.TRUE ;
-                }
-                if ( nv.isDecimal() ) 
-                {
-                    if ( nv.getDecimal().compareTo(BigDecimal.ZERO) == 0 )
-                        return NodeValue.FALSE ;
-                    return NodeValue.TRUE ;
-                }
-                
-                if ( nv.isInteger() )
-                {
-                    if ( nv.getInteger().compareTo(BigInteger.ZERO) == 0 )
-                        return NodeValue.FALSE ;
-                    return NodeValue.TRUE ;
-                }
-            }
-            
-            if ( nv.isBoolean() )
-                return nv ;
-            return super.cast(s, nv, castType) ;
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/jena/blob/5156ba64/jena-arq/src/main/java/org/apache/jena/sparql/function/CastXSD_DateTime.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/function/CastXSD_DateTime.java b/jena-arq/src/main/java/org/apache/jena/sparql/function/CastXSD_DateTime.java
deleted file mode 100644
index eab9b96..0000000
--- a/jena-arq/src/main/java/org/apache/jena/sparql/function/CastXSD_DateTime.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * 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 org.apache.jena.sparql.function;
-
-import org.apache.jena.datatypes.xsd.XSDDatatype ;
-import org.apache.jena.sparql.expr.NodeValue ;
-import org.apache.jena.sparql.expr.nodevalue.XSDFuncOp ;
-import org.apache.jena.sparql.util.NodeUtils ;
-
-
-/** Cast DateTime */
-public class CastXSD_DateTime extends CastXSD implements FunctionFactory
-{
-    public CastXSD_DateTime(XSDDatatype dt)
-    {
-        super(dt) ;
-    }
-    
-    @Override
-    public Function create(String uri)
-    {        
-        return new InstanceDT(castType) ;
-    }
-
-    protected static class InstanceDT extends CastXSD.Instance 
-    {
-        InstanceDT(XSDDatatype dt) { super(dt) ; }
-
-        @Override
-        protected NodeValue cast(String s, NodeValue nv, XSDDatatype castType)
-        {
-            // Plain cast.
-            if ( nv.isString() ||  NodeUtils.hasLang(nv.asNode()) ) 
-                return super.cast(s, nv, castType) ;
-            return XSDFuncOp.dateTimeCast(nv, castType) ;
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/jena/blob/5156ba64/jena-arq/src/main/java/org/apache/jena/sparql/function/CastXSD_Numeric.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/function/CastXSD_Numeric.java b/jena-arq/src/main/java/org/apache/jena/sparql/function/CastXSD_Numeric.java
deleted file mode 100644
index ce9ee5b..0000000
--- a/jena-arq/src/main/java/org/apache/jena/sparql/function/CastXSD_Numeric.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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 org.apache.jena.sparql.function;
-
-import org.apache.jena.datatypes.xsd.XSDDatatype ;
-import org.apache.jena.sparql.expr.NodeValue ;
-import org.apache.jena.sparql.expr.nodevalue.XSDFuncOp ;
-
-public class CastXSD_Numeric extends CastXSD
-{
-    public CastXSD_Numeric(XSDDatatype dt)
-    {
-        super(dt) ;
-    }
-    
-    @Override
-    public Function create(String uri)
-    {        
-        return new Instance(castType) ;
-    }
-
-
-    protected static class Instance extends CastXSD.Instance 
-    {
-        Instance(XSDDatatype dt)
-        {
-            super(dt) ;
-        }
-
-        @Override
-        protected NodeValue cast(String s, NodeValue nv, XSDDatatype castType)
-        {
-            if ( nv.isBoolean() )
-            {
-                boolean b = nv.getBoolean() ;
-                if ( XSDDatatype.XSDfloat.equals(castType) || XSDDatatype.XSDdouble.equals(castType) )
-                    s = ( b ? "1.0E0" : "0.0E0" ) ;
-                else if ( XSDDatatype.XSDdecimal.equals(castType) )
-                    s = ( b ? "1.0" : "0.0" ) ;
-                else if ( XSDFuncOp.isIntegerType(castType)) 
-                    s = ( b ? "1" : "0" ) ;
-                // else do nothing and hope. 
-            }
-            
-            return super.cast(s, nv, castType) ;
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/jena/blob/5156ba64/jena-arq/src/main/java/org/apache/jena/sparql/function/StandardFunctions.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/function/StandardFunctions.java b/jena-arq/src/main/java/org/apache/jena/sparql/function/StandardFunctions.java
index 320d9ba..a988bdd 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/function/StandardFunctions.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/function/StandardFunctions.java
@@ -54,21 +54,21 @@ public class StandardFunctions
         addCastNumeric(registry, XSDDatatype.XSDdouble) ;
         addCastNumeric(registry, XSDDatatype.XSDfloat) ;
         
-        addCastBoolean(registry, XSDDatatype.XSDboolean) ;
-
-        addCast(registry, XSDDatatype.XSDduration) ;
-        addCast(registry, XSDDatatype.XSDstring) ;
-        addCast(registry, XSDDatatype.XSDanyURI) ;
+        addCastXSD(registry, XSDDatatype.XSDboolean) ;
+        addCastXSD(registry, XSDDatatype.XSDduration) ;
+        addCastXSD(registry, XSDDatatype.XSDdayTimeDuration) ;
+        addCastXSD(registry, XSDDatatype.XSDyearMonthDuration) ;
+        addCastXSD(registry, XSDDatatype.XSDstring) ;
+        addCastXSD(registry, XSDDatatype.XSDanyURI) ;
         
-        // Specialized casting rules
-        addCastDT(registry, XSDDatatype.XSDdateTime) ;
-        addCastDT(registry, XSDDatatype.XSDdate) ;
-        addCastDT(registry, XSDDatatype.XSDtime) ;
-        addCastDT(registry, XSDDatatype.XSDgYear) ;
-        addCastDT(registry, XSDDatatype.XSDgYearMonth) ;
-        addCastDT(registry, XSDDatatype.XSDgMonth) ;
-        addCastDT(registry, XSDDatatype.XSDgMonthDay) ;
-        addCastDT(registry, XSDDatatype.XSDgDay) ;
+        addCastTemporal(registry, XSDDatatype.XSDdateTime) ;
+        addCastTemporal(registry, XSDDatatype.XSDdate) ;
+        addCastTemporal(registry, XSDDatatype.XSDtime) ;
+        addCastTemporal(registry, XSDDatatype.XSDgYear) ;
+        addCastTemporal(registry, XSDDatatype.XSDgYearMonth) ;
+        addCastTemporal(registry, XSDDatatype.XSDgMonth) ;
+        addCastTemporal(registry, XSDDatatype.XSDgMonthDay) ;
+        addCastTemporal(registry, XSDDatatype.XSDgDay) ;
 
         //TODO op:numeric-greater-than etc.
         
@@ -114,24 +114,19 @@ public class StandardFunctions
         add(registry, xfn+"seconds-from-duration",  FN_SecondsFromDuration.class) ;
     }
     
-    private static void addCast(FunctionRegistry registry, XSDDatatype dt)
+    private static void addCastXSD(FunctionRegistry registry, XSDDatatype dt)
     {
-        registry.put(dt.getURI(), new CastXSD(dt) ) ;
+        registry.put(dt.getURI(), new CastXSD2(dt) ) ;
     }
     
     private static void addCastNumeric(FunctionRegistry registry, XSDDatatype dt)
     {
-        registry.put(dt.getURI(), new CastXSD_Numeric(dt) ) ;
-    }
-
-    private static void addCastBoolean(FunctionRegistry registry, XSDDatatype dt)
-    {
-        registry.put(dt.getURI(), new CastXSD_Boolean(dt) ) ;
+        registry.put(dt.getURI(), new CastXSD2(dt) ) ;
     }
 
-    private static void addCastDT(FunctionRegistry registry, XSDDatatype dt)
+    private static void addCastTemporal(FunctionRegistry registry, XSDDatatype dt)
     {
-        registry.put(dt.getURI(), new CastXSD_DateTime(dt) ) ;
+        registry.put(dt.getURI(), new CastXSD2(dt) ) ;
     }
 
     private static void add(FunctionRegistry registry, String uri, Class<?> funcClass)

http://git-wip-us.apache.org/repos/asf/jena/blob/5156ba64/jena-arq/src/test/java/org/apache/jena/sparql/expr/TS_Expr.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/expr/TS_Expr.java b/jena-arq/src/test/java/org/apache/jena/sparql/expr/TS_Expr.java
index f2f3abd..bf0ae6d 100644
--- a/jena-arq/src/test/java/org/apache/jena/sparql/expr/TS_Expr.java
+++ b/jena-arq/src/test/java/org/apache/jena/sparql/expr/TS_Expr.java
@@ -32,6 +32,7 @@ import org.junit.runners.Suite.SuiteClasses ;
     , TestExpressions.class
     , TestExpressions2.class
     , TestExpressions3.class
+    , TestCastXSD.class
     , TestNodeFunctions.class
     , TestExpressions2.class
     , TestFunctions.class

http://git-wip-us.apache.org/repos/asf/jena/blob/5156ba64/jena-arq/src/test/java/org/apache/jena/sparql/expr/TestCastXSD.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/expr/TestCastXSD.java b/jena-arq/src/test/java/org/apache/jena/sparql/expr/TestCastXSD.java
new file mode 100644
index 0000000..d382494
--- /dev/null
+++ b/jena-arq/src/test/java/org/apache/jena/sparql/expr/TestCastXSD.java
@@ -0,0 +1,136 @@
+/**
+ * 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 org.apache.jena.sparql.expr;
+
+import org.apache.jena.graph.Node ;
+import org.apache.jena.query.ARQ ;
+import org.apache.jena.sparql.ARQConstants ;
+import org.apache.jena.sparql.engine.ExecutionContext ;
+import org.apache.jena.sparql.expr.Expr ;
+import org.apache.jena.sparql.expr.ExprEvalException ;
+import org.apache.jena.sparql.expr.NodeValue ;
+import org.apache.jena.sparql.function.FunctionEnv ;
+import org.apache.jena.sparql.sse.SSE ;
+import org.apache.jena.sparql.util.ExprUtils ;
+import org.apache.jena.sparql.util.NodeFactoryExtra ;
+import org.junit.AfterClass ;
+import org.junit.Assert ;
+import org.junit.BeforeClass ;
+import org.junit.Test ;
+
+public class TestCastXSD {
+    
+    private static boolean origValue ;
+    @BeforeClass public static void beforeClass() {
+        origValue = NodeValue.VerboseWarnings;
+        NodeValue.VerboseWarnings = false ;
+    }
+    @AfterClass public static void afterClass() {
+        NodeValue.VerboseWarnings = origValue ;
+    }
+
+    @Test public void cast_to_integer_01()  { testCast      ("xsd:integer('1e0'^^xsd:double)",      "'1'^^xsd:integer") ; }
+    @Test public void cast_to_integer_02()  { testCast      ("xsd:byte('1e0'^^xsd:double)",         "'1'^^xsd:byte") ; }
+    @Test public void cast_to_integer_03()  { testNoCast    ("xsd:byte('HaHa'^^xsd:double)") ; }
+    @Test public void cast_to_integer_04()  { testCast      ("xsd:byte('-1'^^xsd:double)",          "'-1'^^xsd:byte") ; }
+    @Test public void cast_to_integer_05()  { testNoCast    ("xsd:unsignedInt('-1'^^xsd:double)") ; }
+    @Test public void cast_to_integer_06()  { testNoCast    ("xsd:byte('500'^^xsd:float)") ; }
+    @Test public void cast_to_integer_07()  { testCast      ("xsd:integer('1e20'^^xsd:double)",     "100000000000000000000") ; }
+    @Test public void cast_to_integer_08()  { testCast      ("xsd:integer('1e19'^^xsd:double)",     "10000000000000000000") ; }
+    @Test public void cast_to_integer_09()  { testCast      ("xsd:integer('1e18'^^xsd:double)",     "1000000000000000000") ; }
+    @Test public void cast_to_integer_10()  { testCast      ("xsd:integer('+1'^^xsd:integer)",      "'+1'^^xsd:integer") ; }
+    @Test public void cast_to_integer_11()  { testCast      ("xsd:byte('+1'^^xsd:integer)",         "'+1'^^xsd:byte") ; }
+    @Test public void cast_to_integer_12()  { testNoCast    ("xsd:byte('HaHa'^^xsd:integer)") ; }
+    @Test public void cast_to_integer_13()  { testCast      ("xsd:byte('-1'^^xsd:integer)",         "'-1'^^xsd:byte") ; }
+    @Test public void cast_to_integer_14()  { testNoCast    ("xsd:unsignedInt('-1'^^xsd:integer)") ; }
+    @Test public void cast_to_integer_15()  { testNoCast    ("xsd:byte('500'^^xsd:integer)") ; }
+    @Test public void cast_to_integer_16()  { testCast      ("xsd:decimal('1000000000000'^^xsd:integer)",  "'1000000000000'^^xsd:decimal") ; }
+    @Test public void cast_to_integer_17()  { testCast      ("xsd:int('1000'^^xsd:integer)",        "'1000'^^xsd:int") ; }
+    @Test public void cast_to_integer_18()  { testCast      ("xsd:integer('1000'^^xsd:int)",        "'1000'^^xsd:integer") ; }
+    @Test public void cast_to_integer_19()  { testNoCast    ("xsd:negativeInteger('1000'^^xsd:int)") ; }
+    @Test public void cast_to_integer_20()  { testCast      ("xsd:integer('+1'^^xsd:decimal)",      "'1'^^xsd:integer") ; }
+    @Test public void cast_to_integer_21()  { testNoCast    ("xsd:integer('1.4'^^xsd:decimal)") ; }
+    @Test public void cast_to_integer_22()  { testCast      ("xsd:byte('01.0'^^xsd:decimal)",       "'1'^^xsd:byte") ; }
+    @Test public void cast_to_integer_23()  { testNoCast    ("xsd:byte('HaHa'^^xsd:decimal)") ; }
+    @Test public void cast_to_integer_24()  { testCast      ("xsd:byte('-1'^^xsd:decimal)",         "'-1'^^xsd:byte") ; }
+    @Test public void cast_to_integer_25()  { testNoCast    ("xsd:unsignedInt('-1'^^xsd:decimal)") ; }
+    @Test public void cast_to_integer_26()  { testNoCast    ("xsd:byte('500'^^xsd:decimal)") ; }
+
+    @Test public void cast_decimal_10()     { testCast      ("xsd:decimal('1e-20'^^xsd:double)",    "0.00000000000000000001") ; }
+    @Test public void cast_decimal_11()     { testCast      ("xsd:decimal('1e-19'^^xsd:double)",        "0.0000000000000000001") ; }
+    @Test public void cast_decimal_12()     { testCast      ("xsd:decimal('1e-18'^^xsd:double)",        "0.000000000000000001") ; }
+
+    @Test public void cast_from_string_01() { testCast      ("xsd:integer('+1'^^xsd:string)",           "'+1'^^xsd:integer") ; }
+    @Test public void cast_from_string_02() { testNoCast    ("xsd:integer('a'^^xsd:string)") ; }
+    @Test public void cast_from_string_03() { testCast      ("xsd:integer('11')",                       "'11'^^xsd:integer") ; }
+    @Test public void cast_from_string_04() { testCast      ("xsd:double('12'^^xsd:string)",            "'12'^^xsd:double") ; }
+    @Test public void cast_from_string_05() { testNoCast    ("xsd:double('abc'^^xsd:string)") ; }
+
+    @Test public void cast_from_boolean_01() { testCast     ("xsd:boolean('true'^^xsd:boolean)",         "'true'^^xsd:boolean" ) ; }
+    @Test public void cast_from_boolean_02() { testCast     ("xsd:boolean('1'^^xsd:boolean)",            "'1'^^xsd:boolean" ) ; }
+    @Test public void cast_from_boolean_03() { testCast     ("xsd:integer('1'^^xsd:boolean)",            "1" ) ; }
+    @Test public void cast_from_boolean_04() { testCast     ("xsd:decimal('false'^^xsd:boolean)",        "0.0" ) ; }
+    @Test public void cast_from_boolean_05() { testCast     ("xsd:double('false'^^xsd:boolean)",         "0.0E0" ) ; }
+
+    @Test public void cast_to_duration_01()  { testCast     ("xsd:duration('PT10S')",                            "'PT10S'^^xsd:duration") ; }   
+    @Test public void cast_to_duration_02()  { testCast     ("xsd:duration('P1DT10S'^^xsd:dayTimeDuration)",     "'P1DT10S'^^xsd:duration") ; } 
+
+    @Test public void cast_to_duration_03()  { testCast     ("xsd:dayTimeDuration('P1Y2M3DT1H2M3S'^^xsd:duration)",   "'P3DT1H2M3S'^^xsd:dayTimeDuration") ; }   
+    @Test public void cast_to_duration_04()  { testCast     ("xsd:dayTimeDuration('P1Y'^^xsd:duration)",          "'PT0S'^^xsd:dayTimeDuration") ; }   
+    @Test public void cast_to_duration_05()  { testCast     ("xsd:yearMonthDuration('P1Y2M3DT1H2M3S'^^xsd:duration)", "'P1Y2M'^^xsd:yearMonthDuration") ; }
+
+    // This is what the XSD spec says, not "no cast"
+    @Test public void cast_to_duration_06()  { testCast     ("xsd:dayTimeDuration('P1Y2M'^^xsd:yearMonthDuration)",   "'PT0S'^^xsd:dayTimeDuration") ; }
+    @Test public void cast_to_duration_07()  { testCast     ("xsd:yearMonthDuration('P1DT10H'^^xsd:dayTimeDuration)", "'P0M'^^xsd:yearMonthDuration") ; }
+    @Test public void cast_to_duration_08()  { testCast     ("xsd:yearMonthDuration('P1Y2M')",                      "'P1Y2M'^^xsd:yearMonthDuration") ; }
+    @Test public void cast_to_duration_09()  { testCast     ("xsd:dayTimeDuration('P1DT10H')",                      "'P1DT10H'^^xsd:dayTimeDuration") ; }
+    @Test public void cast_to_duration_10()  { testCast     ("xsd:duration('P1Y2M3DT1H2M3S')",                      "'P1Y2M3DT1H2M3S'^^xsd:duration") ; }
+
+    @Test public void cast_to_temporal_01() { testCast      ("xsd:date('2015-10-12T15:00:24'^^xsd:dateTime)",         "'2015-10-12'^^xsd:date") ; }
+    @Test public void cast_to_temporal_02() { testCast      ("xsd:date('2015-10-12T15:00:24+01:00'^^xsd:dateTime)",   "'2015-10-12+01:00'^^xsd:date") ; }
+    @Test public void cast_to_temporal_03() { testCast      ("xsd:dateTime('2015-10-12'^^xsd:date)",                  "'2015-10-12T00:00:00'^^xsd:dateTime") ; }
+    @Test public void cast_to_temporal_04() { testCast      ("xsd:dateTime('2015-10-12+01:00'^^xsd:date)",            "'2015-10-12T00:00:00+01:00'^^xsd:dateTime") ; }
+    @Test public void cast_to_temporal_05() { testCast      ("xsd:time('2015-10-12T15:00:24'^^xsd:dateTime)",         "'15:00:24'^^xsd:time") ; }
+    @Test public void cast_to_temporal_06() { testCast      ("xsd:dateTime('2015-10-12T15:00:24Z')",               "'2015-10-12T15:00:24Z'^^xsd:dateTime") ; }
+
+    @Test public void cast_to_gregorian_01() { testCast     ("xsd:gYear('2015-10-12'^^xsd:date)",        "'2015'^^xsd:gYear") ; }
+    @Test public void cast_to_gregorian_02() { testCast     ("xsd:gMonth('2015-10-12'^^xsd:date)",       "'--10'^^xsd:gMonth") ; }
+    @Test public void cast_to_gregorian_03() { testCast     ("xsd:gMonthDay('2015-10-12'^^xsd:date)",    "'--10-12'^^xsd:gMonthDay") ; }
+    @Test public void cast_to_gregorian_04() { testCast     ("xsd:gYearMonth('2015-10-12'^^xsd:date)",   "'2015-10'^^xsd:gYearMonth") ; }
+
+    private void testNoCast(String input) {
+        try {
+            cast(input) ;
+            Assert.fail("Expected ExprEvalException") ;
+        } catch (ExprEvalException ex) {}
+    }
+
+    private void testCast(String input, String output) {
+        NodeValue nv2 = cast(input) ;
+        Node expected = SSE.parseNode(output) ;
+        Assert.assertEquals(expected, nv2.asNode()) ;
+    }
+
+    private NodeValue cast(String input$) {
+        Expr input = ExprUtils.parse(input$) ;
+        ARQ.getContext().set(ARQConstants.sysCurrentTime, NodeFactoryExtra.nowAsDateTime()) ;
+        FunctionEnv env = new ExecutionContext(ARQ.getContext(), null, null, null) ; 
+        return input.eval(null, env) ;
+    }
+}
\ No newline at end of file


[4/4] jena git commit: JENA-1047: Rename to CastXSD

Posted by an...@apache.org.
JENA-1047: Rename to CastXSD


Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/d3180b5e
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/d3180b5e
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/d3180b5e

Branch: refs/heads/master
Commit: d3180b5e75b8842cb201fa2bc73843025957ba70
Parents: 5156ba6
Author: Andy Seaborne <an...@apache.org>
Authored: Mon Oct 12 18:15:34 2015 +0100
Committer: Andy Seaborne <an...@apache.org>
Committed: Mon Oct 12 18:15:34 2015 +0100

----------------------------------------------------------------------
 .../apache/jena/sparql/function/CastXSD.java    | 317 +++++++++++++++++++
 .../apache/jena/sparql/function/CastXSD2.java   | 317 -------------------
 .../jena/sparql/function/StandardFunctions.java |   6 +-
 3 files changed, 320 insertions(+), 320 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jena/blob/d3180b5e/jena-arq/src/main/java/org/apache/jena/sparql/function/CastXSD.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/function/CastXSD.java b/jena-arq/src/main/java/org/apache/jena/sparql/function/CastXSD.java
new file mode 100644
index 0000000..b3c3837
--- /dev/null
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/function/CastXSD.java
@@ -0,0 +1,317 @@
+/**
+ * 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 org.apache.jena.sparql.function;
+
+import java.math.BigDecimal ;
+import java.math.BigInteger ;
+import java.util.Objects ;
+
+import javax.xml.datatype.DatatypeConstants ;
+import javax.xml.datatype.Duration ;
+
+import org.apache.jena.datatypes.xsd.XSDDatatype ;
+import org.apache.jena.datatypes.xsd.impl.XSDAbstractDateTimeType ;
+import org.apache.jena.datatypes.xsd.impl.XSDBaseNumericType ;
+import org.apache.jena.graph.Node ;
+import org.apache.jena.sparql.expr.ExprEvalException ;
+import org.apache.jena.sparql.expr.ExprEvalTypeException ;
+import org.apache.jena.sparql.expr.ExprException ;
+import org.apache.jena.sparql.expr.NodeValue ;
+import org.apache.jena.sparql.expr.nodevalue.XSDFuncOp ;
+
+public class CastXSD extends FunctionBase1 implements FunctionFactory {
+    
+    protected final XSDDatatype castType ;
+    
+    public CastXSD(XSDDatatype dt)
+    {
+        this.castType = dt ; 
+    }
+    
+    @Override
+    public Function create(String uri)
+    {        
+        return this ;
+    }
+    
+    @Override
+    public NodeValue exec(NodeValue v)
+    {
+        return cast(v, castType) ;
+    }
+
+    
+    private static boolean isTemporalDatatype(XSDDatatype datatype) {
+        return 
+            datatype.equals(XSDDatatype.XSDdateTime) ||
+            datatype.equals(XSDDatatype.XSDtime) ||
+            datatype.equals(XSDDatatype.XSDdate) ||
+            datatype.equals(XSDDatatype.XSDgYear) ||
+            datatype.equals(XSDDatatype.XSDgYearMonth) ||
+            datatype.equals(XSDDatatype.XSDgMonth) ||
+            datatype.equals(XSDDatatype.XSDgMonthDay) ||
+            datatype.equals(XSDDatatype.XSDgDay) ;
+    }
+    
+    private static boolean isDurationDatatype(XSDDatatype datatype) {
+        return 
+            datatype.equals(XSDDatatype.XSDduration) || 
+            datatype.equals(XSDDatatype.XSDyearMonthDuration) ||
+            datatype.equals(XSDDatatype.XSDdayTimeDuration ) ;
+    }
+    
+    /** Cast a NodeValue to an XSD datatype.
+     * This includes "by value" so 1e0 (an xsd:double) casts to 1 (an xsd:intger) 
+     * @param nv
+     * @param castType
+     * @return NodeValue
+     * @throws ExprEvalException
+     */
+    public static NodeValue cast(NodeValue nv, XSDDatatype castType) {
+        // http://www.w3.org/TR/xpath-functions/#casting
+        Node n = nv.asNode() ;
+    
+        if ( n.isBlank() )
+            throw exception("Can't cast blank nodes: "+nv) ;
+    
+        if ( n.isURI() ) {
+            if ( castType.equals(XSDDatatype.XSDstring) )
+                return cast$(n.getURI(), castType) ;
+            else
+                throw exception("Can't cast URIs to "+castType.getURI()) ;
+        }
+    
+        if ( ! n.isLiteral() )
+            throw exception("Can't cast (not a literal, nor URI to string) "+nv+" : "+castType.getURI()) ;
+
+        // It's a literal.
+        
+        // Cast to self but may be an  invalid lexical form.
+        if ( Objects.equals(nv.getNode().getLiteralDatatype(), castType) ) {
+            String lex = nv.getNode().getLiteralLexicalForm() ;
+            if ( castType.isValid(lex) )
+                return nv ;
+            throw exception("Invalid lexical form for "+castType.getURI()) ;  
+        }
+
+        
+        // Many casts can be done by testing the lexical is valid for the datatype.
+        // But some cases need to consider values.
+        //  e.g. boolean -> numeric , double -> integer (doubles have "e" in them)
+        
+        // To a temporal
+        if ( isTemporalDatatype(castType) ) {
+            return XSDFuncOp.dateTimeCast(nv, castType) ;
+        }
+        
+        if ( isDurationDatatype(castType) ) {
+            // Duration cast.
+            // yearMonthDuration and TT is xs:dayTimeDuration -> 0.0S
+            // xs:dayTimeDuration and TT is yearMonthDuration -> P0M
+            
+            if ( nv.isDuration() ) {
+                Duration d = nv.getDuration() ;
+                if ( castType.equals(XSDDatatype.XSDyearMonthDuration) ) {
+                    
+                    // Include xsd:duration only covering year-month.
+                    if ( nv.isDayTimeDuration() )
+                        return NodeValue.makeNode("P0M", castType) ;
+                    
+                    Duration d2 =  NodeValue.xmlDatatypeFactory.newDuration
+                        (d.getSign()>=0,
+                            (BigInteger)d.getField(DatatypeConstants.YEARS), (BigInteger)d.getField(DatatypeConstants.MONTHS), null,
+                        null, null, null) ;
+                    return NodeValue.makeNode(d2.toString(), castType) ;
+                }
+                if ( castType.equals(XSDDatatype.XSDdayTimeDuration) ) {
+                    if ( nv.isYearMonthDuration() )
+                        return NodeValue.makeNode("PT0S", castType) ;
+                    Duration d2 =  NodeValue.xmlDatatypeFactory.newDuration
+                        
+                        (d.getSign()>=0,
+                        null, null, (BigInteger)d.getField(DatatypeConstants.DAYS),
+                        (BigInteger)d.getField(DatatypeConstants.HOURS), (BigInteger)d.getField(DatatypeConstants.MINUTES), (BigDecimal)d.getField(DatatypeConstants.SECONDS)) ;
+                    // return NodeValue.makeDuration(d2) ;
+                    return NodeValue.makeNode(d2.toString(), castType) ;
+                }
+            }
+        }
+
+        // From number, can consider value.
+        if ( nv.isNumber() ) {
+            if ( castType.equals(XSDDatatype.XSDdecimal) ) {   
+                // Number to decimal.
+                if ( isDouble(nv) || isFloat(nv) ) {
+                    // FP to decimal.
+                    double d = nv.getDouble() ;
+                    if ( Double.isNaN(d) )
+                        throw exception("Can't cast NaN to xsd:decimal") ;
+                    if ( Double.isInfinite(d) )
+                        throw exception("Can't cast Inf or -Inf to xsd:decimal") ;
+                    // BigDecimal.valueOf(d) can lead to trailing zeros
+                    // BigDecimal.valueOf(d) goes via strings.
+                    String lex = doubleToDecimalString(d) ;
+                    return NodeValue.makeDecimal(lex) ;
+                }
+                // Integer, or derived type -> decimal. 
+                return castByLex(nv, castType) ;
+            }
+            if ( XSDFuncOp.isIntegerType(castType) ) {
+                // Number to integer
+                if ( isDouble(nv) || isFloat(nv) ) {
+                    // FP to integer
+                    double d = nv.getDouble() ;
+                    boolean isIntegerValue = ( Math.rint(d) == d ) ;
+                    if ( isIntegerValue ) {
+                        String lex = doubleIntegerToString(d) ;
+                        if ( lex != null )
+                            return castByLex(lex, castType) ;
+                    }
+                    throw exception(nv, castType) ;
+                } else if ( isDecimal(nv) ) {
+                    // Decimal to integer
+                    BigDecimal bd = nv.getDecimal() ;
+                    try {
+                        // Exception on fraction. 
+                        BigInteger bi = bd.toBigIntegerExact() ;
+                        return castByLex(bi.toString(), castType) ;
+                    } catch (ArithmeticException ex) {
+                        throw new ExprEvalException("CastXSD: Not a valid cast: '"+nv+"'") ;
+                    }
+                } else {
+                    // Integer derived type -> integer derived type.
+                    return castByLex(nv, castType) ;
+                }
+            }
+        }
+    
+        // Boolean -> xsd:
+        if ( nv.isBoolean() ) { 
+            boolean b = nv.getBoolean() ;
+            // Boolean to boolean covered above.
+            String lex ;
+            if ( XSDDatatype.XSDfloat.equals(castType) || XSDDatatype.XSDdouble.equals(castType) )
+                return cast$( ( b ? "1.0E0" : "0.0E0" ) , castType) ;
+            else if ( XSDDatatype.XSDdecimal.equals(castType) )
+                return cast$( ( b ? "1.0" : "0.0" ) , castType) ;
+            else if ( XSDFuncOp.isIntegerType(castType)) 
+                return cast$(  ( b ? "1" : "0" ) , castType ) ;
+            else if ( XSDDatatype.XSDstring.equals(castType) ) 
+                return cast$( nv.getNode().getLiteralLexicalForm(), castType ) ;
+            throw exception("Can't cast xsd:boolean to "+castType) ;
+        }
+
+        // Try by lexical
+        return castByLex(nv, castType) ;
+    }
+
+    /** Presentation form of an XSD datatype URI */
+    private static String xsdName(String datatype) {
+        return datatype.replaceAll(XSDDatatype.XSD+"#", "xsd:") ;
+    }
+
+    /** Test to see if a NodeValue is a valid double value and is of datatype xsd:double. */ 
+    private static boolean isDouble(NodeValue nv) {
+        return nv.isDouble() && nv.getDatatypeURI().equals(XSDDatatype.XSDdouble.getURI()) ;
+    }
+
+    /** Test to see if a NodeValue is a valid float value and is of datatype float. */ 
+    private static boolean isFloat(NodeValue nv) {
+        return nv.isFloat() && nv.getDatatypeURI().equals(XSDDatatype.XSDfloat.getURI()) ;
+    }
+
+    /** Test to see if a NodeValue is a valid decimal value and is of datatype decimal. */ 
+    private static boolean isDecimal(NodeValue nv) {
+        return nv.isDecimal() && nv.getDatatypeURI().equals(XSDDatatype.XSDdecimal.getURI()) ;
+    }
+
+    /** Test to see if a NodeValue is a valid numeric value. */ 
+    private static boolean isNumeric(NodeValue nv) {
+        return nv.isNumber() ;
+    }
+
+    private static ExprException exception(NodeValue nv, XSDDatatype dt) {
+        return exception("Invalid cast: "+nv+" -> "+xsdName(dt.getURI())) ;
+    }
+    
+    private static ExprException exception(String msg) {
+        return new ExprEvalTypeException(msg) ;
+    }
+
+    // Cast by lexical form with checking.
+    private static NodeValue castByLex(NodeValue nv, XSDDatatype castType) {
+        String lex = nv.getNode().getLiteralLexicalForm() ;
+        return castByLex(lex, castType) ;
+    }
+
+    // Cast by lexical form with checking.
+    private static NodeValue castByLex(String lex, XSDDatatype castType) {
+        if ( ! castType.isValid(lex) )
+            throw exception("Invalid lexical form: '"+lex+"' for "+castType.getURI()) ;
+        if ( castType instanceof XSDBaseNumericType || 
+            castType.equals(XSDDatatype.XSDfloat) ||
+            castType.equals(XSDDatatype.XSDdouble) ||
+            castType.equals(XSDDatatype.XSDboolean) ||
+            castType instanceof XSDAbstractDateTimeType )   // Includes durations, and Gregorian
+        {
+            // More helpful error message.
+            if ( lex.startsWith(" ") || lex.endsWith(" ") )
+                throw exception("Not a valid literal form (has whitespace): '"+lex+"'") ;
+        }
+        return NodeValue.makeNode(lex, castType) ;
+
+    }
+
+    // Known to work casts.  No checking.
+    private static NodeValue cast$(String lex, XSDDatatype castType) {
+        return NodeValue.makeNode(lex, castType) ;
+    }
+
+    // Return the integer lexical form for a double, where the double is known to be integer valued.
+    private static String doubleIntegerToString(double d) {
+        // Fast path
+        long x = Math.round(d) ;
+        if ( x != Long.MAX_VALUE && x != Long.MIN_VALUE )
+            return  Long.toString(x) ;
+
+        String lex = BigDecimal.valueOf(d).toPlainString() ;
+        int i = lex.indexOf('.') ;
+        if ( i >= 0 )
+            // Adds .0 for some (small) doubles. 
+            lex = lex.substring(0, i) ;
+        return lex;
+    }
+
+    // Return the decimal lexical form for a double value.
+    // Java big decimal allows "E" forms, XSD does not.
+    private static String doubleToDecimalString(double d) {
+        // BigDecimal.valueOf(d) can lead to trailing zeros.
+        String lex = BigDecimal.valueOf(d).toPlainString() ;
+        // Clean the string. 
+        int i = lex.indexOf('.') ;
+        if ( i < 0 )
+            return lex ;
+        // Often one or two
+        while(lex.endsWith("00"))
+            lex = lex.substring(0,  lex.length()-2) ;
+        while(lex.endsWith("0"))
+            lex = lex.substring(0,  lex.length()-1) ;
+        return lex ;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jena/blob/d3180b5e/jena-arq/src/main/java/org/apache/jena/sparql/function/CastXSD2.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/function/CastXSD2.java b/jena-arq/src/main/java/org/apache/jena/sparql/function/CastXSD2.java
deleted file mode 100644
index 6d742b3..0000000
--- a/jena-arq/src/main/java/org/apache/jena/sparql/function/CastXSD2.java
+++ /dev/null
@@ -1,317 +0,0 @@
-/**
- * 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 org.apache.jena.sparql.function;
-
-import java.math.BigDecimal ;
-import java.math.BigInteger ;
-import java.util.Objects ;
-
-import javax.xml.datatype.DatatypeConstants ;
-import javax.xml.datatype.Duration ;
-
-import org.apache.jena.datatypes.xsd.XSDDatatype ;
-import org.apache.jena.datatypes.xsd.impl.XSDAbstractDateTimeType ;
-import org.apache.jena.datatypes.xsd.impl.XSDBaseNumericType ;
-import org.apache.jena.graph.Node ;
-import org.apache.jena.sparql.expr.ExprEvalException ;
-import org.apache.jena.sparql.expr.ExprEvalTypeException ;
-import org.apache.jena.sparql.expr.ExprException ;
-import org.apache.jena.sparql.expr.NodeValue ;
-import org.apache.jena.sparql.expr.nodevalue.XSDFuncOp ;
-
-public class CastXSD2 extends FunctionBase1 implements FunctionFactory {
-    
-    protected final XSDDatatype castType ;
-    
-    public CastXSD2(XSDDatatype dt)
-    {
-        this.castType = dt ; 
-    }
-    
-    @Override
-    public Function create(String uri)
-    {        
-        return this ;
-    }
-    
-    @Override
-    public NodeValue exec(NodeValue v)
-    {
-        return cast(v, castType) ;
-    }
-
-    
-    private static boolean isTemporalDatatype(XSDDatatype datatype) {
-        return 
-            datatype.equals(XSDDatatype.XSDdateTime) ||
-            datatype.equals(XSDDatatype.XSDtime) ||
-            datatype.equals(XSDDatatype.XSDdate) ||
-            datatype.equals(XSDDatatype.XSDgYear) ||
-            datatype.equals(XSDDatatype.XSDgYearMonth) ||
-            datatype.equals(XSDDatatype.XSDgMonth) ||
-            datatype.equals(XSDDatatype.XSDgMonthDay) ||
-            datatype.equals(XSDDatatype.XSDgDay) ;
-    }
-    
-    private static boolean isDurationDatatype(XSDDatatype datatype) {
-        return 
-            datatype.equals(XSDDatatype.XSDduration) || 
-            datatype.equals(XSDDatatype.XSDyearMonthDuration) ||
-            datatype.equals(XSDDatatype.XSDdayTimeDuration ) ;
-    }
-    
-    /** Cast a NodeValue to an XSD datatype.
-     * This includes "by value" so 1e0 (an xsd:double) casts to 1 (an xsd:intger) 
-     * @param nv
-     * @param castType
-     * @return NodeValue
-     * @throws ExprEvalException
-     */
-    public static NodeValue cast(NodeValue nv, XSDDatatype castType) {
-        // http://www.w3.org/TR/xpath-functions/#casting
-        Node n = nv.asNode() ;
-    
-        if ( n.isBlank() )
-            throw exception("Can't cast blank nodes: "+nv) ;
-    
-        if ( n.isURI() ) {
-            if ( castType.equals(XSDDatatype.XSDstring) )
-                return cast$(n.getURI(), castType) ;
-            else
-                throw exception("Can't cast URIs to "+castType.getURI()) ;
-        }
-    
-        if ( ! n.isLiteral() )
-            throw exception("Can't cast (not a literal, nor URI to string) "+nv+" : "+castType.getURI()) ;
-
-        // It's a literal.
-        
-        // Cast to self but may be an  invalid lexical form.
-        if ( Objects.equals(nv.getNode().getLiteralDatatype(), castType) ) {
-            String lex = nv.getNode().getLiteralLexicalForm() ;
-            if ( castType.isValid(lex) )
-                return nv ;
-            throw exception("Invalid lexical form for "+castType.getURI()) ;  
-        }
-
-        
-        // Many casts can be done by testing the lexical is valid for the datatype.
-        // But some cases need to consider values.
-        //  e.g. boolean -> numeric , double -> integer (doubles have "e" in them)
-        
-        // To a temporal
-        if ( isTemporalDatatype(castType) ) {
-            return XSDFuncOp.dateTimeCast(nv, castType) ;
-        }
-        
-        if ( isDurationDatatype(castType) ) {
-            // Duration cast.
-            // yearMonthDuration and TT is xs:dayTimeDuration -> 0.0S
-            // xs:dayTimeDuration and TT is yearMonthDuration -> P0M
-            
-            if ( nv.isDuration() ) {
-                Duration d = nv.getDuration() ;
-                if ( castType.equals(XSDDatatype.XSDyearMonthDuration) ) {
-                    
-                    // Include xsd:duration only covering year-month.
-                    if ( nv.isDayTimeDuration() )
-                        return NodeValue.makeNode("P0M", castType) ;
-                    
-                    Duration d2 =  NodeValue.xmlDatatypeFactory.newDuration
-                        (d.getSign()>=0,
-                            (BigInteger)d.getField(DatatypeConstants.YEARS), (BigInteger)d.getField(DatatypeConstants.MONTHS), null,
-                        null, null, null) ;
-                    return NodeValue.makeNode(d2.toString(), castType) ;
-                }
-                if ( castType.equals(XSDDatatype.XSDdayTimeDuration) ) {
-                    if ( nv.isYearMonthDuration() )
-                        return NodeValue.makeNode("PT0S", castType) ;
-                    Duration d2 =  NodeValue.xmlDatatypeFactory.newDuration
-                        
-                        (d.getSign()>=0,
-                        null, null, (BigInteger)d.getField(DatatypeConstants.DAYS),
-                        (BigInteger)d.getField(DatatypeConstants.HOURS), (BigInteger)d.getField(DatatypeConstants.MINUTES), (BigDecimal)d.getField(DatatypeConstants.SECONDS)) ;
-                    // return NodeValue.makeDuration(d2) ;
-                    return NodeValue.makeNode(d2.toString(), castType) ;
-                }
-            }
-        }
-
-        // From number, can consider value.
-        if ( nv.isNumber() ) {
-            if ( castType.equals(XSDDatatype.XSDdecimal) ) {   
-                // Number to decimal.
-                if ( isDouble(nv) || isFloat(nv) ) {
-                    // FP to decimal.
-                    double d = nv.getDouble() ;
-                    if ( Double.isNaN(d) )
-                        throw exception("Can't cast NaN to xsd:decimal") ;
-                    if ( Double.isInfinite(d) )
-                        throw exception("Can't cast Inf or -Inf to xsd:decimal") ;
-                    // BigDecimal.valueOf(d) can lead to trailing zeros
-                    // BigDecimal.valueOf(d) goes via strings.
-                    String lex = doubleToDecimalString(d) ;
-                    return NodeValue.makeDecimal(lex) ;
-                }
-                // Integer, or derived type -> decimal. 
-                return castByLex(nv, castType) ;
-            }
-            if ( XSDFuncOp.isIntegerType(castType) ) {
-                // Number to integer
-                if ( isDouble(nv) || isFloat(nv) ) {
-                    // FP to integer
-                    double d = nv.getDouble() ;
-                    boolean isIntegerValue = ( Math.rint(d) == d ) ;
-                    if ( isIntegerValue ) {
-                        String lex = doubleIntegerToString(d) ;
-                        if ( lex != null )
-                            return castByLex(lex, castType) ;
-                    }
-                    throw exception(nv, castType) ;
-                } else if ( isDecimal(nv) ) {
-                    // Decimal to integer
-                    BigDecimal bd = nv.getDecimal() ;
-                    try {
-                        // Exception on fraction. 
-                        BigInteger bi = bd.toBigIntegerExact() ;
-                        return castByLex(bi.toString(), castType) ;
-                    } catch (ArithmeticException ex) {
-                        throw new ExprEvalException("CastXSD: Not a valid cast: '"+nv+"'") ;
-                    }
-                } else {
-                    // Integer derived type -> integer derived type.
-                    return castByLex(nv, castType) ;
-                }
-            }
-        }
-    
-        // Boolean -> xsd:
-        if ( nv.isBoolean() ) { 
-            boolean b = nv.getBoolean() ;
-            // Boolean to boolean covered above.
-            String lex ;
-            if ( XSDDatatype.XSDfloat.equals(castType) || XSDDatatype.XSDdouble.equals(castType) )
-                return cast$( ( b ? "1.0E0" : "0.0E0" ) , castType) ;
-            else if ( XSDDatatype.XSDdecimal.equals(castType) )
-                return cast$( ( b ? "1.0" : "0.0" ) , castType) ;
-            else if ( XSDFuncOp.isIntegerType(castType)) 
-                return cast$(  ( b ? "1" : "0" ) , castType ) ;
-            else if ( XSDDatatype.XSDstring.equals(castType) ) 
-                return cast$( nv.getNode().getLiteralLexicalForm(), castType ) ;
-            throw exception("Can't cast xsd:boolean to "+castType) ;
-        }
-
-        // Try by lexical
-        return castByLex(nv, castType) ;
-    }
-
-    /** Presentation form of an XSD datatype URI */
-    private static String xsdName(String datatype) {
-        return datatype.replaceAll(XSDDatatype.XSD+"#", "xsd:") ;
-    }
-
-    /** Test to see if a NodeValue is a valid double value and is of datatype xsd:double. */ 
-    private static boolean isDouble(NodeValue nv) {
-        return nv.isDouble() && nv.getDatatypeURI().equals(XSDDatatype.XSDdouble.getURI()) ;
-    }
-
-    /** Test to see if a NodeValue is a valid float value and is of datatype float. */ 
-    private static boolean isFloat(NodeValue nv) {
-        return nv.isFloat() && nv.getDatatypeURI().equals(XSDDatatype.XSDfloat.getURI()) ;
-    }
-
-    /** Test to see if a NodeValue is a valid decimal value and is of datatype decimal. */ 
-    private static boolean isDecimal(NodeValue nv) {
-        return nv.isDecimal() && nv.getDatatypeURI().equals(XSDDatatype.XSDdecimal.getURI()) ;
-    }
-
-    /** Test to see if a NodeValue is a valid numeric value. */ 
-    private static boolean isNumeric(NodeValue nv) {
-        return nv.isNumber() ;
-    }
-
-    private static ExprException exception(NodeValue nv, XSDDatatype dt) {
-        return exception("Invalid cast: "+nv+" -> "+xsdName(dt.getURI())) ;
-    }
-    
-    private static ExprException exception(String msg) {
-        return new ExprEvalTypeException(msg) ;
-    }
-
-    // Cast by lexical form with checking.
-    private static NodeValue castByLex(NodeValue nv, XSDDatatype castType) {
-        String lex = nv.getNode().getLiteralLexicalForm() ;
-        return castByLex(lex, castType) ;
-    }
-
-    // Cast by lexical form with checking.
-    private static NodeValue castByLex(String lex, XSDDatatype castType) {
-        if ( ! castType.isValid(lex) )
-            throw exception("Invalid lexical form: '"+lex+"' for "+castType.getURI()) ;
-        if ( castType instanceof XSDBaseNumericType || 
-            castType.equals(XSDDatatype.XSDfloat) ||
-            castType.equals(XSDDatatype.XSDdouble) ||
-            castType.equals(XSDDatatype.XSDboolean) ||
-            castType instanceof XSDAbstractDateTimeType )   // Includes durations, and Gregorian
-        {
-            // More helpful error message.
-            if ( lex.startsWith(" ") || lex.endsWith(" ") )
-                throw exception("Not a valid literal form (has whitespace): '"+lex+"'") ;
-        }
-        return NodeValue.makeNode(lex, castType) ;
-
-    }
-
-    // Known to work casts.  No checking.
-    private static NodeValue cast$(String lex, XSDDatatype castType) {
-        return NodeValue.makeNode(lex, castType) ;
-    }
-
-    // Return the integer lexical form for a double, where the double is known to be integer valued.
-    private static String doubleIntegerToString(double d) {
-        // Fast path
-        long x = Math.round(d) ;
-        if ( x != Long.MAX_VALUE && x != Long.MIN_VALUE )
-            return  Long.toString(x) ;
-
-        String lex = BigDecimal.valueOf(d).toPlainString() ;
-        int i = lex.indexOf('.') ;
-        if ( i >= 0 )
-            // Adds .0 for some (small) doubles. 
-            lex = lex.substring(0, i) ;
-        return lex;
-    }
-
-    // Return the decimal lexical form for a double value.
-    // Java big decimal allows "E" forms, XSD does not.
-    private static String doubleToDecimalString(double d) {
-        // BigDecimal.valueOf(d) can lead to trailing zeros.
-        String lex = BigDecimal.valueOf(d).toPlainString() ;
-        // Clean the string. 
-        int i = lex.indexOf('.') ;
-        if ( i < 0 )
-            return lex ;
-        // Often one or two
-        while(lex.endsWith("00"))
-            lex = lex.substring(0,  lex.length()-2) ;
-        while(lex.endsWith("0"))
-            lex = lex.substring(0,  lex.length()-1) ;
-        return lex ;
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jena/blob/d3180b5e/jena-arq/src/main/java/org/apache/jena/sparql/function/StandardFunctions.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/function/StandardFunctions.java b/jena-arq/src/main/java/org/apache/jena/sparql/function/StandardFunctions.java
index a988bdd..ac0dbe1 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/function/StandardFunctions.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/function/StandardFunctions.java
@@ -116,17 +116,17 @@ public class StandardFunctions
     
     private static void addCastXSD(FunctionRegistry registry, XSDDatatype dt)
     {
-        registry.put(dt.getURI(), new CastXSD2(dt) ) ;
+        registry.put(dt.getURI(), new CastXSD(dt) ) ;
     }
     
     private static void addCastNumeric(FunctionRegistry registry, XSDDatatype dt)
     {
-        registry.put(dt.getURI(), new CastXSD2(dt) ) ;
+        registry.put(dt.getURI(), new CastXSD(dt) ) ;
     }
 
     private static void addCastTemporal(FunctionRegistry registry, XSDDatatype dt)
     {
-        registry.put(dt.getURI(), new CastXSD2(dt) ) ;
+        registry.put(dt.getURI(), new CastXSD(dt) ) ;
     }
 
     private static void add(FunctionRegistry registry, String uri, Class<?> funcClass)


[2/4] jena git commit: Removed deprecated; add float to string

Posted by an...@apache.org.
Removed deprecated; add float to string


Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/7aa9af5f
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/7aa9af5f
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/7aa9af5f

Branch: refs/heads/master
Commit: 7aa9af5fe8aeb92b32ff9c8e11a6016dee28787e
Parents: b111837
Author: Andy Seaborne <an...@apache.org>
Authored: Mon Oct 12 16:55:50 2015 +0100
Committer: Andy Seaborne <an...@apache.org>
Committed: Mon Oct 12 16:55:50 2015 +0100

----------------------------------------------------------------------
 .../java/org/apache/jena/sparql/util/Utils.java | 24 +++++---------------
 1 file changed, 6 insertions(+), 18 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jena/blob/7aa9af5f/jena-arq/src/main/java/org/apache/jena/sparql/util/Utils.java
----------------------------------------------------------------------
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/util/Utils.java b/jena-arq/src/main/java/org/apache/jena/sparql/util/Utils.java
index 617f7d7..0c1a9ea 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/util/Utils.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/util/Utils.java
@@ -20,27 +20,9 @@ package org.apache.jena.sparql.util ;
 
 import java.math.BigDecimal ;
 
-import org.apache.jena.atlas.lib.Lib ;
-
 /** Miscellaneous operations - not query specific */
 
 public class Utils {
-    /**
-     * @deprecated Use {@link Lib#className(Object)} instead
-     */
-    @Deprecated
-    static public String className(Object obj) {
-        return Lib.className(obj) ;
-    }
-
-    /**
-     * @deprecated Use {@link Lib#classShortName(Class)} instead
-     */
-    @Deprecated
-    static public String classShortName(Class<? > cls) {
-        return Lib.classShortName(cls) ;
-    }
-
     static public String stringForm(BigDecimal decimal) {
         return decimal.toPlainString() ;
     }
@@ -64,6 +46,12 @@ public class Utils {
     }
 
     static public String stringForm(float f) {
+        if ( Float.isInfinite(f) ) {
+            if ( f < 0 )
+                return "-INF" ;
+            return "INF" ;
+        }
+        
         // No SPARQL short form.
         return Float.toString(f) ;
     }