You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by rv...@apache.org on 2014/09/17 13:20:09 UTC

svn commit: r1625517 - in /jena/trunk/jena-arq/src: main/java/com/hp/hpl/jena/sparql/expr/nodevalue/XSDFuncOp.java main/java/com/hp/hpl/jena/sparql/function/library/FN_StrLength.java test/java/com/hp/hpl/jena/sparql/expr/TestFunctions.java

Author: rvesse
Date: Wed Sep 17 11:20:08 2014
New Revision: 1625517

URL: http://svn.apache.org/r1625517
Log:
Fix SUBSTR() and STRLEN() to follow the XPath specification and compute substrings and lengths based on complete code points not Java characters (JENA-785)

Modified:
    jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/nodevalue/XSDFuncOp.java
    jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/function/library/FN_StrLength.java
    jena/trunk/jena-arq/src/test/java/com/hp/hpl/jena/sparql/expr/TestFunctions.java

Modified: jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/nodevalue/XSDFuncOp.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/nodevalue/XSDFuncOp.java?rev=1625517&r1=1625516&r2=1625517&view=diff
==============================================================================
--- jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/nodevalue/XSDFuncOp.java (original)
+++ jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/expr/nodevalue/XSDFuncOp.java Wed Sep 17 11:20:08 2014
@@ -357,7 +357,7 @@ public class XSDFuncOp
                 return NodeValue.makeString(string.substring(start)) ;
 
             int finish = nvFinish.getInteger().intValue() ;
-            return NodeValue.makeString(string.substring(start, finish)) ;
+            return NodeValue.makeString(string.substring(start, string.offsetByCodePoints(start, finish - start))) ;
         } catch (IndexOutOfBoundsException ex) {
             throw new ExprEvalException("IndexOutOfBounds", ex) ;
         }
@@ -365,7 +365,8 @@ public class XSDFuncOp
 
     public static NodeValue strlen(NodeValue nvString) {
         Node n = checkAndGetStringLiteral("strlen", nvString) ;
-        int len = n.getLiteralLexicalForm().length() ;
+        String str = n.getLiteralLexicalForm();
+        int len = str.codePointCount(0, str.length()) ;
         return NodeValue.makeInteger(len) ;
     }
 
@@ -475,7 +476,7 @@ public class XSDFuncOp
             if ( string.length() == 0 )
                 return calcReturn("", n) ;
 
-            String lex2 = string.substring(start, finish) ;
+            String lex2 = string.substring(start, string.offsetByCodePoints(start, finish - start)) ;
             return calcReturn(lex2, n) ;
         } catch (IndexOutOfBoundsException ex) {
             throw new ExprEvalException("IndexOutOfBounds", ex) ;

Modified: jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/function/library/FN_StrLength.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/function/library/FN_StrLength.java?rev=1625517&r1=1625516&r2=1625517&view=diff
==============================================================================
--- jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/function/library/FN_StrLength.java (original)
+++ jena/trunk/jena-arq/src/main/java/com/hp/hpl/jena/sparql/function/library/FN_StrLength.java Wed Sep 17 11:20:08 2014
@@ -19,6 +19,7 @@
 package com.hp.hpl.jena.sparql.function.library;
 
 import com.hp.hpl.jena.sparql.expr.NodeValue ;
+import com.hp.hpl.jena.sparql.expr.nodevalue.XSDFuncOp;
 import com.hp.hpl.jena.sparql.function.FunctionBase1 ;
 
 /** string length - F&O operation */
@@ -30,6 +31,6 @@ public class FN_StrLength extends Functi
     @Override
     public NodeValue exec(NodeValue v)
     {
-        return NodeValue.makeInteger(v.getString().length()) ;
+        return XSDFuncOp.strlen(v);
     }
 }

Modified: jena/trunk/jena-arq/src/test/java/com/hp/hpl/jena/sparql/expr/TestFunctions.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-arq/src/test/java/com/hp/hpl/jena/sparql/expr/TestFunctions.java?rev=1625517&r1=1625516&r2=1625517&view=diff
==============================================================================
--- jena/trunk/jena-arq/src/test/java/com/hp/hpl/jena/sparql/expr/TestFunctions.java (original)
+++ jena/trunk/jena-arq/src/test/java/com/hp/hpl/jena/sparql/expr/TestFunctions.java Wed Sep 17 11:20:08 2014
@@ -33,6 +33,7 @@ public class TestFunctions
 {
     private static final NodeValue INT_ZERO = NodeValue.makeInteger(0) ;
     private static final NodeValue INT_ONE  = NodeValue.makeInteger(1) ;
+    @SuppressWarnings("unused")
     private static final NodeValue INT_TWO  = NodeValue.makeInteger(2) ;
     private static final NodeValue TRUE     = NodeValue.TRUE ;
     private static final NodeValue FALSE    = NodeValue.FALSE ;
@@ -41,6 +42,8 @@ public class TestFunctions
 
     @Test public void exprStrLen1() { test("fn:string-length('')", INT_ZERO) ; }
     @Test public void exprStrLen2() { test("fn:string-length('a')", INT_ONE) ; }
+    // Test from JENA-785
+    @Test public void exprStrLen3() { test("fn:string-length('𐐈𐑌𐐻𐐪𐑉𐐿𐐻𐐮𐐿𐐲')", NodeValue.makeInteger(10l)) ; }
 
     // F&O strings are one-based, and substring takes a length
     @Test public void exprSubstring1() { test("fn:substring('',0)", NodeValue.makeString("")) ; }
@@ -58,12 +61,15 @@ public class TestFunctions
     @Test public void exprSubstring10() { test("fn:substring('abc',1.6,1.33)", NodeValue.makeString("b")) ; }
     // This test was added because the test suite had 1199 tests in. 
     @Test public void exprSubstring11() { test("fn:substring('abc',-1, -15.3)", NodeValue.makeString("")) ; }
+    // Test from JENA-785
+    @Test public void exprSubstring12() { test("fn:substring('𐐈𐑌𐐻𐐪𐑉𐐿𐐻𐐮𐐿𐐲', 1, 1)", NodeValue.makeString("𐐈")) ; } 
     
     @Test public void exprJavaSubstring1() { test("afn:substr('abc',0,0)", NodeValue.makeString("")) ; }
     @Test public void exprJavaSubstring2() { test("afn:substr('abc',0,1)", NodeValue.makeString("a")) ; }
-
     @Test public void exprJavaSubstring3() { test("<"+ARQConstants.ARQFunctionLibrary+"substr>('abc',0,0)", NodeValue.makeString("")) ; }
     @Test public void exprJavaSubstring4() { test("<"+ARQConstants.ARQFunctionLibrary+"substr>('abc',0,1)", NodeValue.makeString("a")) ; }
+    // Test from JENA-785
+    @Test public void exprJavaSubstring5() { test("afn:substr('𐐈𐑌𐐻𐐪𐑉𐐿𐐻𐐮𐐿𐐲', 0, 1)", NodeValue.makeString("𐐈")) ; }
     
     @Test public void exprStrStart0() { test("fn:starts-with('abc', '')", TRUE) ; }
     @Test public void exprStrStart1() { test("fn:starts-with('abc', 'a')", TRUE) ; }