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 2025/04/25 13:43:38 UTC
(jena) 01/05: Move argument checking library code to NodeValueOps
This is an automated email from the ASF dual-hosted git repository.
andy pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/jena.git
commit ad4f7f23787424d462836af2c650a2cbd6b453d4
Author: Andy Seaborne <an...@apache.org>
AuthorDate: Sun Apr 20 11:27:49 2025 +0100
Move argument checking library code to NodeValueOps
---
.../java/org/apache/jena/sparql/expr/E_Regex.java | 4 +-
.../org/apache/jena/sparql/expr/E_Subtract.java | 1 -
.../jena/sparql/expr/nodevalue/NodeFunctions.java | 67 ------------------
.../jena/sparql/expr/nodevalue/NodeValueOps.java | 80 +++++++++++++++++++++-
.../jena/sparql/expr/nodevalue/XSDFuncOp.java | 32 ++++-----
.../apache/jena/sparql/expr/TestNodeFunctions.java | 31 +--------
.../apache/jena/sparql/expr/TestNodeValueOps.java | 31 +++++++++
7 files changed, 128 insertions(+), 118 deletions(-)
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/expr/E_Regex.java b/jena-arq/src/main/java/org/apache/jena/sparql/expr/E_Regex.java
index 94f14e752f..eaa58e299a 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/expr/E_Regex.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/expr/E_Regex.java
@@ -24,7 +24,7 @@ import org.apache.commons.lang3.StringUtils ;
import org.apache.jena.atlas.logging.Log ;
import org.apache.jena.graph.Node ;
import org.apache.jena.query.ARQ ;
-import org.apache.jena.sparql.expr.nodevalue.NodeFunctions ;
+import org.apache.jena.sparql.expr.nodevalue.NodeValueOps;
import org.apache.jena.sparql.sse.Tags ;
import org.apache.jena.sparql.util.FmtUtils ;
@@ -62,7 +62,7 @@ public class E_Regex extends ExprFunctionN
@Override
public NodeValue eval(List<NodeValue> args) {
- Node arg = NodeFunctions.checkAndGetStringLiteral("REGEX", args.get(0));
+ Node arg = NodeValueOps.checkAndGetStringLiteral("REGEX", args.get(0));
NodeValue vPattern = args.get(1);
NodeValue vFlags = (args.size() == 2 ? null : args.get(2));
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/expr/E_Subtract.java b/jena-arq/src/main/java/org/apache/jena/sparql/expr/E_Subtract.java
index 846a981e4c..904e692286 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/expr/E_Subtract.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/expr/E_Subtract.java
@@ -38,7 +38,6 @@ public class E_Subtract extends ExprFunction2
{
if ( ARQ.isStrictMode() )
return XSDFuncOp.numSubtract(x, y) ;
-
return NodeValueOps.subtractionNV(x, y) ;
}
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/expr/nodevalue/NodeFunctions.java b/jena-arq/src/main/java/org/apache/jena/sparql/expr/nodevalue/NodeFunctions.java
index 0d04b2021f..4dfef10acc 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/expr/nodevalue/NodeFunctions.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/expr/nodevalue/NodeFunctions.java
@@ -53,73 +53,6 @@ import org.apache.jena.vocabulary.XSD;
*/
public class NodeFunctions {
- /**
- * check and get a string (may be a simple literal, literal with language
- * tag or an XSD string).
- */
- public static Node checkAndGetStringLiteral(String label, NodeValue nv) {
- Node n = nv.asNode();
- if ( !n.isLiteral() )
- throw new ExprEvalException(label + ": Not a literal: " + nv);
- String lang = n.getLiteralLanguage();
-
- if ( NodeUtils.isLangString(n) )
- // Language tag. Legal.
- return n;
-
- // No language tag : either no datatype or a datatype of xsd:string
- // Includes the case of rdf:langString and no language ==> Illegal as a compatible string.
-
- if ( nv.isString() )
- return n;
- throw new ExprEvalException(label + ": Not a string literal: " + nv);
- }
-
- /**
- * Check for string operations with primary first arg and second arg
- * (e.g. CONTAINS). The arguments are not used in the same way and the check
- * operation is not symmetric.
- * <ul>
- * <li> "abc"@en is compatible with "abc"
- * <li> "abc" is NOT compatible with "abc"@en
- * </ul>
- */
- public static void checkTwoArgumentStringLiterals(String label, NodeValue arg1, NodeValue arg2) {
-
- /* Quote the spec:
- * Compatibility of two arguments is defined as:
- * The arguments are simple literals or literals typed as xsd:string
- * The arguments are plain literals with identical language tags
- * The first argument is a plain literal with language tag and the second argument is a simple literal or literal typed as xsd:string
- */
-
- Node n1 = checkAndGetStringLiteral(label, arg1);
- Node n2 = checkAndGetStringLiteral(label, arg2);
- String lang1 = n1.getLiteralLanguage();
- String lang2 = n2.getLiteralLanguage();
- if ( lang1 == null )
- lang1 = "";
- if ( lang2 == null )
- lang2 = "";
-
- // Case 1
- if ( lang1.equals("") ) {
- if ( lang2.equals("") )
- return;
- throw new ExprEvalException(label + ": Incompatible: " + arg1 + " and " + arg2);
- }
-
- // Case 2
- if ( lang1.equalsIgnoreCase(lang2) )
- return;
-
- // Case 3
- if ( lang2.equals("") )
- return;
-
- throw new ExprEvalException(label + ": Incompatible: " + arg1 + " and " + arg2);
- }
-
// -------- sameTerm
public static NodeValue sameTerm(NodeValue nv1, NodeValue nv2) {
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/expr/nodevalue/NodeValueOps.java b/jena-arq/src/main/java/org/apache/jena/sparql/expr/nodevalue/NodeValueOps.java
index f1fc4a2ad5..b76ddf2460 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/expr/nodevalue/NodeValueOps.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/expr/nodevalue/NodeValueOps.java
@@ -30,11 +30,20 @@ import javax.xml.datatype.XMLGregorianCalendar;
import org.apache.jena.datatypes.xsd.XSDDatatype;
import org.apache.jena.graph.Node;
import org.apache.jena.graph.NodeFactory;
+import org.apache.jena.sparql.expr.ExprEvalException;
import org.apache.jena.sparql.expr.ExprEvalTypeException;
import org.apache.jena.sparql.expr.NodeValue;
import org.apache.jena.sparql.expr.ValueSpace;
-
-/** The code parts of arithmetic operations on {@link NodeValue}s.
+import org.apache.jena.sparql.util.NodeUtils;
+
+/**
+ * Operations relating to {@link NodeValue NodeValues}.
+ * <ul>
+ * <li>The code parts of arithmetic operations on {@link NodeValue}s.
+ * <li>Library code such as Argument testing
+ * </ul>
+ * <p>
+ * This class is not considered to be part of the ARQ API.
*/
public class NodeValueOps
{
@@ -284,4 +293,71 @@ public class NodeValueOps
long x2 = gcal2.getTimeInMillis();
return NodeValue.xmlDatatypeFactory.newDuration(x1 - x2);
}
+
+ /**
+ * check and get a string (may be a simple literal, literal with language
+ * tag or an XSD string).
+ */
+ public static Node checkAndGetStringLiteral(String label, NodeValue nv) {
+ Node n = nv.asNode();
+ if ( !n.isLiteral() )
+ throw new ExprEvalException(label + ": Not a literal: " + nv);
+ String lang = n.getLiteralLanguage();
+
+ if ( NodeUtils.isLangString(n) )
+ // Language tag. Legal.
+ return n;
+
+ // No language tag : either no datatype or a datatype of xsd:string
+ // Includes the case of rdf:langString and no language ==> Illegal as a compatible string.
+
+ if ( nv.isString() )
+ return n;
+ throw new ExprEvalException(label + ": Not a string literal: " + nv);
+ }
+
+ /**
+ * Check for string operations with primary first arg and second arg
+ * (e.g. CONTAINS). The arguments are not used in the same way and the check
+ * operation is not symmetric.
+ * <ul>
+ * <li> "abc"@en is compatible with "abc"
+ * <li> "abc" is NOT compatible with "abc"@en
+ * </ul>
+ */
+ public static void checkTwoArgumentStringLiterals(String label, NodeValue arg1, NodeValue arg2) {
+
+ /* Quote the spec:
+ * Compatibility of two arguments is defined as:
+ * The arguments are simple literals or literals typed as xsd:string
+ * The arguments are plain literals with identical language tags
+ * The first argument is a plain literal with language tag and the second argument is a simple literal or literal typed as xsd:string
+ */
+
+ Node n1 = checkAndGetStringLiteral(label, arg1);
+ Node n2 = checkAndGetStringLiteral(label, arg2);
+ String lang1 = n1.getLiteralLanguage();
+ String lang2 = n2.getLiteralLanguage();
+ if ( lang1 == null )
+ lang1 = "";
+ if ( lang2 == null )
+ lang2 = "";
+
+ // Case 1
+ if ( lang1.equals("") ) {
+ if ( lang2.equals("") )
+ return;
+ throw new ExprEvalException(label + ": Incompatible: " + arg1 + " and " + arg2);
+ }
+
+ // Case 2
+ if ( lang1.equalsIgnoreCase(lang2) )
+ return;
+
+ // Case 3
+ if ( lang2.equals("") )
+ return;
+
+ throw new ExprEvalException(label + ": Incompatible: " + arg1 + " and " + arg2);
+ }
}
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 fa049da431..4a17dbc04c 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
@@ -19,8 +19,6 @@
package org.apache.jena.sparql.expr.nodevalue;
import static javax.xml.datatype.DatatypeConstants.*;
-import static org.apache.jena.sparql.expr.nodevalue.NodeFunctions.checkAndGetStringLiteral;
-import static org.apache.jena.sparql.expr.nodevalue.NodeFunctions.checkTwoArgumentStringLiterals;
import static org.apache.jena.sparql.expr.nodevalue.NumericType.OP_DECIMAL;
import static org.apache.jena.sparql.expr.nodevalue.NumericType.OP_DOUBLE;
import static org.apache.jena.sparql.expr.nodevalue.NumericType.OP_FLOAT;
@@ -63,7 +61,7 @@ public class XSDFuncOp
{
private XSDFuncOp() {}
- // The choice of "24" is arbitrary but more than 18 (XSD 1.0) or 16 XSD 1.1) as required by F&O
+ // The choice of "24" is arbitrary but more than 18 (XSD 1.0) or 16 (XSD 1.1) as required by F&O
// F&O 3.1: section 4.2 (end intro)
// https://www.w3.org/TR/xpath-functions/#op.numeric section 4.2
private static final int DIVIDE_PRECISION = 24;
@@ -556,23 +554,23 @@ public class XSDFuncOp
}
public static NodeValue strlen(NodeValue nvString) {
- Node n = checkAndGetStringLiteral("strlen", nvString);
+ Node n = NodeValueOps.checkAndGetStringLiteral("strlen", nvString);
String str = n.getLiteralLexicalForm();
int len = str.codePointCount(0, str.length());
return NodeValue.makeInteger(len);
}
public static NodeValue strReplace(NodeValue nvStr, NodeValue nvPattern, NodeValue nvReplacement, NodeValue nvFlags) {
- String pat = checkAndGetStringLiteral("replace", nvPattern).getLiteralLexicalForm();
+ String pat = NodeValueOps.checkAndGetStringLiteral("replace", nvPattern).getLiteralLexicalForm();
String flagsStr = null;
if ( nvFlags != null )
- flagsStr = checkAndGetStringLiteral("replace", nvFlags).getLiteralLexicalForm();
+ flagsStr = NodeValueOps.checkAndGetStringLiteral("replace", nvFlags).getLiteralLexicalForm();
return strReplace(nvStr, RegexEngine.makePattern("replace", pat, flagsStr), nvReplacement);
}
public static NodeValue strReplace(NodeValue nvStr, Pattern pattern, NodeValue nvReplacement) {
- String n = checkAndGetStringLiteral("replace", nvStr).getLiteralLexicalForm();
- String rep = checkAndGetStringLiteral("replace", nvReplacement).getLiteralLexicalForm();
+ String n = NodeValueOps.checkAndGetStringLiteral("replace", nvStr).getLiteralLexicalForm();
+ String rep = NodeValueOps.checkAndGetStringLiteral("replace", nvReplacement).getLiteralLexicalForm();
String x = replaceAll(pattern.matcher(n), rep);
if ( x == null )
// No replacement.
@@ -621,7 +619,7 @@ public class XSDFuncOp
}
public static NodeValue substring(NodeValue nvString, NodeValue nvStart, NodeValue nvLength) {
- Node n = checkAndGetStringLiteral("substring", nvString);
+ Node n = NodeValueOps.checkAndGetStringLiteral("substring", nvString);
RDFDatatype dt = n.getLiteralDatatype();
// XSD F&O:
try {
@@ -708,7 +706,7 @@ public class XSDFuncOp
}
public static NodeValue strContains(NodeValue string, NodeValue match) {
- checkTwoArgumentStringLiterals("contains", string, match);
+ NodeValueOps.checkTwoArgumentStringLiterals("contains", string, match);
String lex1 = string.asNode().getLiteralLexicalForm();
String lex2 = match.asNode().getLiteralLexicalForm();
boolean x = StrUtils.contains(lex1, lex2);
@@ -716,14 +714,14 @@ public class XSDFuncOp
}
public static NodeValue strStartsWith(NodeValue string, NodeValue match) {
- checkTwoArgumentStringLiterals("strStarts", string, match);
+ NodeValueOps.checkTwoArgumentStringLiterals("strStarts", string, match);
String lex1 = string.asNode().getLiteralLexicalForm();
String lex2 = match.asNode().getLiteralLexicalForm();
return NodeValue.booleanReturn(lex1.startsWith(lex2));
}
public static NodeValue strEndsWith(NodeValue string, NodeValue match) {
- checkTwoArgumentStringLiterals("strEnds", string, match);
+ NodeValueOps.checkTwoArgumentStringLiterals("strEnds", string, match);
String lex1 = string.asNode().getLiteralLexicalForm();
String lex2 = match.asNode().getLiteralLexicalForm();
return NodeValue.booleanReturn(lex1.endsWith(lex2));
@@ -736,7 +734,7 @@ public class XSDFuncOp
}
public static NodeValue strBefore(NodeValue string, NodeValue match) {
- checkTwoArgumentStringLiterals("strBefore", string, match);
+ NodeValueOps.checkTwoArgumentStringLiterals("strBefore", string, match);
String lex1 = string.asNode().getLiteralLexicalForm();
String lex2 = match.asNode().getLiteralLexicalForm();
Node mainArg = string.asNode();
@@ -753,7 +751,7 @@ public class XSDFuncOp
}
public static NodeValue strAfter(NodeValue string, NodeValue match) {
- checkTwoArgumentStringLiterals("strAfter", string, match);
+ NodeValueOps.checkTwoArgumentStringLiterals("strAfter", string, match);
String lex1 = string.asNode().getLiteralLexicalForm();
String lex2 = match.asNode().getLiteralLexicalForm();
Node mainArg = string.asNode();
@@ -770,14 +768,14 @@ public class XSDFuncOp
}
public static NodeValue strLowerCase(NodeValue string) {
- Node n = checkAndGetStringLiteral("lcase", string);
+ Node n = NodeValueOps.checkAndGetStringLiteral("lcase", string);
String lex = n.getLiteralLexicalForm();
String lex2 = lex.toLowerCase();
return calcReturn(lex2, string.asNode());
}
public static NodeValue strUpperCase(NodeValue string) {
- Node n = checkAndGetStringLiteral("ucase", string);
+ Node n = NodeValueOps.checkAndGetStringLiteral("ucase", string);
String lex = n.getLiteralLexicalForm();
String lex2 = lex.toUpperCase();
return calcReturn(lex2, string.asNode());
@@ -820,7 +818,7 @@ public class XSDFuncOp
StringBuilder sb = new StringBuilder();
for (NodeValue nv : args) {
- Node n = checkAndGetStringLiteral("CONCAT", nv);
+ Node n = NodeValueOps.checkAndGetStringLiteral("CONCAT", nv);
String lang1 = n.getLiteralLanguage();
if ( !lang1.equals("") ) {
if ( lang != null && !lang1.equals(lang) )
diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/expr/TestNodeFunctions.java b/jena-arq/src/test/java/org/apache/jena/sparql/expr/TestNodeFunctions.java
index ab46dbb938..1491c3c96d 100644
--- a/jena-arq/src/test/java/org/apache/jena/sparql/expr/TestNodeFunctions.java
+++ b/jena-arq/src/test/java/org/apache/jena/sparql/expr/TestNodeFunctions.java
@@ -20,6 +20,8 @@ package org.apache.jena.sparql.expr;
import static org.junit.Assert.*;
+import org.junit.Test;
+
import org.apache.jena.datatypes.xsd.XSDDatatype;
import org.apache.jena.graph.Node;
import org.apache.jena.graph.NodeFactory;
@@ -28,9 +30,7 @@ import org.apache.jena.query.ARQ;
import org.apache.jena.sparql.expr.nodevalue.NodeFunctions;
import org.apache.jena.sparql.graph.NodeConst;
import org.apache.jena.sparql.sse.SSE;
-import org.apache.jena.vocabulary.RDF;
import org.apache.jena.vocabulary.XSD;
-import org.junit.Test;
public class TestNodeFunctions {
private static final double accuracyExact = 0.0d;
@@ -396,31 +396,4 @@ public class TestNodeFunctions {
NodeValue r = NodeFunctions.isLiteral(nv);
assertEquals(NodeValue.FALSE, r);
}
-
- @Test public void testCheckAndGetStringLiteral1() {
- NodeValue nv = NodeValue.makeNode("abc", XSDDatatype.XSDstring);
- Node n = NodeFunctions.checkAndGetStringLiteral("Test", nv);
- assertEquals( "abc", n.getLiteralLexicalForm());
- }
-
- @Test public void testCheckAndGetStringLiteral2() {
- NodeValue nv = NodeValue.makeNode("abc", XSDDatatype.XSDnormalizedString);
- Node n = NodeFunctions.checkAndGetStringLiteral("Test", nv);
- assertEquals( "abc", n.getLiteralLexicalForm());
- }
-
- @Test public void testCheckAndGetStringLiteral3() {
- NodeValue nv = NodeValue.makeString("abc");
- Node n = NodeFunctions.checkAndGetStringLiteral("Test", nv);
- assertEquals( "abc", n.getLiteralLexicalForm());
- }
-
- @Test(expected=ExprEvalException.class)
- public void testCheckAndGetStringLiteral4() {
- // The form "abc"^^rdf:langString (no lang tag) is not derived from xsd:string.
- NodeValue nv = NodeValue.makeNode("abc", RDF.dtLangString);
- Node n = NodeFunctions.checkAndGetStringLiteral("Test", nv);
- assertEquals( "abc", n.getLiteralLexicalForm());
- }
-
}
diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/expr/TestNodeValueOps.java b/jena-arq/src/test/java/org/apache/jena/sparql/expr/TestNodeValueOps.java
index 7651c9a37f..ff64564e64 100644
--- a/jena-arq/src/test/java/org/apache/jena/sparql/expr/TestNodeValueOps.java
+++ b/jena-arq/src/test/java/org/apache/jena/sparql/expr/TestNodeValueOps.java
@@ -20,10 +20,41 @@ package org.apache.jena.sparql.expr;
import static org.junit.Assert.assertEquals;
+import org.apache.jena.datatypes.xsd.XSDDatatype;
+import org.apache.jena.graph.Node;
import org.apache.jena.sparql.expr.nodevalue.NodeValueOps;
+import org.apache.jena.vocabulary.RDF;
+
import org.junit.Test;
public class TestNodeValueOps {
+
+ @Test public void testCheckAndGetStringLiteral1() {
+ NodeValue nv = NodeValue.makeNode("abc", XSDDatatype.XSDstring);
+ Node n = NodeValueOps.checkAndGetStringLiteral("Test", nv);
+ assertEquals( "abc", n.getLiteralLexicalForm());
+ }
+
+ @Test public void testCheckAndGetStringLiteral2() {
+ NodeValue nv = NodeValue.makeNode("abc", XSDDatatype.XSDnormalizedString);
+ Node n = NodeValueOps.checkAndGetStringLiteral("Test", nv);
+ assertEquals( "abc", n.getLiteralLexicalForm());
+ }
+
+ @Test public void testCheckAndGetStringLiteral3() {
+ NodeValue nv = NodeValue.makeString("abc");
+ Node n = NodeValueOps.checkAndGetStringLiteral("Test", nv);
+ assertEquals( "abc", n.getLiteralLexicalForm());
+ }
+
+ @Test(expected=ExprEvalException.class)
+ public void testCheckAndGetStringLiteral4() {
+ // The form "abc"^^rdf:langString (no lang tag) is not derived from xsd:string.
+ NodeValue nv = NodeValue.makeNode("abc", RDF.dtLangString);
+ Node n = NodeValueOps.checkAndGetStringLiteral("Test", nv);
+ assertEquals( "abc", n.getLiteralLexicalForm());
+ }
+
// ** Addition
// Numerics
@Test