This is an automated email from the ASF dual-hosted git repository.
afs pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/jena.git
The following commit(s) were added to refs/heads/main by this push:
new 3014246b38 GH-2805: Implement VERSION for N-Triples and N-Quads parsing
3014246b38 is described below
commit 3014246b382d2439f4cd81aa72a7383ba0f9b3d5
Author: Andy Seaborne <[email protected]>
AuthorDate: Thu Oct 8 16:14:21 2026 +0100
GH-2805: Implement VERSION for N-Triples and N-Quads parsing
---
.../java/org/apache/jena/riot/lang/LangNQuads.java | 10 ++++-
.../org/apache/jena/riot/lang/LangNTriples.java | 14 ++++---
.../java/org/apache/jena/riot/lang/LangNTuple.java | 46 ++++++++++++++++++++--
.../org/apache/jena/riot/tokens/StringType.java | 2 +-
.../org/apache/jena/riot/lang/TestLangNQuads.java | 24 +++++++++++
.../apache/jena/riot/lang/TestLangNTriples.java | 24 +++++++++++
6 files changed, 107 insertions(+), 13 deletions(-)
diff --git a/jena-arq/src/main/java/org/apache/jena/riot/lang/LangNQuads.java
b/jena-arq/src/main/java/org/apache/jena/riot/lang/LangNQuads.java
index 4f60751738..a38d371b1b 100644
--- a/jena-arq/src/main/java/org/apache/jena/riot/lang/LangNQuads.java
+++ b/jena-arq/src/main/java/org/apache/jena/riot/lang/LangNQuads.java
@@ -53,14 +53,20 @@ public class LangNQuads extends LangNTuple<Quad> {
@Override
protected final void runParser() {
while (hasNext()) {
- Quad x = parseOne();
+ Quad x = parseOneStatement();
if ( x != null )
dest.quad(x);
}
}
@Override
- protected final Quad parseOne() {
+ protected final Quad parseOneStatement() {
+ if ( parsePossibleVersion() )
+ return null;
+ return parseQuad();
+ }
+
+ protected final Quad parseQuad() {
Token token = peekToken();
Node s = parseSubject();
Node p = parsePredicate();
diff --git a/jena-arq/src/main/java/org/apache/jena/riot/lang/LangNTriples.java
b/jena-arq/src/main/java/org/apache/jena/riot/lang/LangNTriples.java
index 39c2595943..2123c84fc8 100644
--- a/jena-arq/src/main/java/org/apache/jena/riot/lang/LangNTriples.java
+++ b/jena-arq/src/main/java/org/apache/jena/riot/lang/LangNTriples.java
@@ -35,32 +35,34 @@ import org.slf4j.LoggerFactory ;
/**
* N-Triples.
- *
+ *
* @see <a
href="http://www.w3.org/TR/n-triples/">http://www.w3.org/TR/n-triples/</a>
*/
public final class LangNTriples extends LangNTuple<Triple>
{
private static Logger messageLog = LoggerFactory.getLogger("N-Triples") ;
-
+
public LangNTriples(Tokenizer tokens, ParserProfile profile, StreamRDF
dest) {
super(tokens, profile, dest) ;
}
-
+
@Override
public Lang getLang() { return RDFLanguages.NTRIPLES ; }
- /** Method to parse the whole stream of triples, sending each to the sink
*/
+ /** Method to parse the whole stream of triples, sending each to the sink
*/
@Override
protected final void runParser() {
while (hasNext()) {
- Triple x = parseOne();
+ Triple x = parseOneStatement();
if ( x != null )
dest.triple(x);
}
}
@Override
- protected final Triple parseOne() {
+ protected final Triple parseOneStatement() {
+ if ( parsePossibleVersion() )
+ return null;
Triple triple = parseTriple();
Token x = nextToken();
if ( x.getType() != TokenType.DOT )
diff --git a/jena-arq/src/main/java/org/apache/jena/riot/lang/LangNTuple.java
b/jena-arq/src/main/java/org/apache/jena/riot/lang/LangNTuple.java
index 29210ebca6..defd5ff1c4 100644
--- a/jena-arq/src/main/java/org/apache/jena/riot/lang/LangNTuple.java
+++ b/jena-arq/src/main/java/org/apache/jena/riot/lang/LangNTuple.java
@@ -69,11 +69,14 @@ public abstract class LangNTuple<X> extends LangBase
implements Iterator<X>
@Override
public final X next() {
- return parseOne();
+ return parseOneStatement();
}
- /** Parse one tuple - return object to be sent to the sink or null for
none */
- protected abstract X parseOne() ;
+ /**
+ * Parse one tuple - return object to be sent to the sink or null for none.
+ * null is returned for VERSION
+ */
+ protected abstract X parseOneStatement() ;
/** Note a tuple not being output */
protected void skipOne(X object, String printForm, long line, long col) {
@@ -82,9 +85,44 @@ public abstract class LangNTuple<X> extends LangBase
implements Iterator<X>
protected abstract Node tokenAsNode(Token token) ;
+ // NT and NQ VERSION keyword. It must be upper case.
+ protected static String kwVERSION = "VERSION";
+
+ /**
+ * Parse a possible VERSION directive.
+ * Return true for seen keyword,
+ * false for not a keyword, including EOF.
+ * Throw error on bad directive.
+ */
+ protected final boolean parsePossibleVersion() {
+ Token token = peekToken();
+ // Parse version lines.
+ if ( token .isEOF() || ! token.hasType(TokenType.KEYWORD) )
+ return false;
+
+ // Keywords
+ nextToken();
+ String KW = token.getImage();
+ if ( ! KW.equals(kwVERSION) )
+ exception(token, "Keyword at start of triple: %s", token);
+
+ // VERSION
+ Token token2 = peekToken();
+ if ( token2.isEOF() )
+ exception(token, "Expected version string after VERSION keyword");
+ expect("Expected string for VERSION", token2.getType());
+
+ StringType stringType = token2.getStringType();
+ if ( stringType != StringType.STRING2 )
+ exception(token, "Expected \"-quoted string for the version");
+ String versionStr = token2.getImage();
+ dest.version(versionStr);
+ return true;
+ }
+
// One triple, not including terminator.
protected final Triple parseTriple() {
- Token token = peekToken();
+ Token token = peekToken(); // Remember for line/column
Node s = parseSubject();
Node p = parsePredicate();
Node o = parseObject();
diff --git a/jena-arq/src/main/java/org/apache/jena/riot/tokens/StringType.java
b/jena-arq/src/main/java/org/apache/jena/riot/tokens/StringType.java
index a9ccf50ae6..1b545a79b5 100644
--- a/jena-arq/src/main/java/org/apache/jena/riot/tokens/StringType.java
+++ b/jena-arq/src/main/java/org/apache/jena/riot/tokens/StringType.java
@@ -25,7 +25,7 @@ package org.apache.jena.riot.tokens;
public enum StringType {
/** A string delimited by 1 single-quote character : {@code 'abc'} */
STRING1,
- /** A string delimited by 1 double-quote character : {@code 'abc'} */
+ /** A string delimited by 1 double-quote character : {@code "abc"} */
STRING2,
/** A string delimited by 3 single-quote characters : {@code '''abc'''} */
LONG_STRING1,
diff --git
a/jena-arq/src/test/java/org/apache/jena/riot/lang/TestLangNQuads.java
b/jena-arq/src/test/java/org/apache/jena/riot/lang/TestLangNQuads.java
index 1ddca8c5fd..0166f268f2 100644
--- a/jena-arq/src/test/java/org/apache/jena/riot/lang/TestLangNQuads.java
+++ b/jena-arq/src/test/java/org/apache/jena/riot/lang/TestLangNQuads.java
@@ -58,6 +58,30 @@ public class TestLangNQuads extends AbstractTestLangNTuples
parseException(ExFatal.class, "<http://example/x> <http://example/p>
<http://example/s> <http://example/g>"); // No trailing DOT
}
+ @Test
+ public void nq_version_1() {
+ parseCheck("""
+ VERSION "1.2"
+ <http://example/s> <http://example/p> <http://example/o>
<http://example/g> .
+ VERSION "1.2"
+ """);
+ }
+
+ @Test
+ public void nq_version_2() {
+ parseCheck("""
+ VERSION "1.2"
+ """);
+ }
+
+ @Test
+ public void nq_version_3() {
+ parseCheck("""
+ VERSION "1.2"
+ VERSION "1.2"
+ """);
+ }
+
@Test
public void nq_only_1_no_tuples() {
parseException(ExFatal.class, "<http://example/x> <http://example/p>
<http://example/s> <http://example/g> <http://example/c> .");
diff --git
a/jena-arq/src/test/java/org/apache/jena/riot/lang/TestLangNTriples.java
b/jena-arq/src/test/java/org/apache/jena/riot/lang/TestLangNTriples.java
index 4482b95d8a..a42e775c60 100644
--- a/jena-arq/src/test/java/org/apache/jena/riot/lang/TestLangNTriples.java
+++ b/jena-arq/src/test/java/org/apache/jena/riot/lang/TestLangNTriples.java
@@ -90,6 +90,30 @@ public class TestLangNTriples extends AbstractTestLangNTuples
assertTrue(g1.isIsomorphicWith(m1.getGraph()));
}
+ @Test
+ public void nt_version_1() {
+ parseCheck("""
+ VERSION "1.2"
+ <http://example/s> <http://example/p> <http://example/o> .
+ VERSION "1.2"
+ """);
+ }
+
+ @Test
+ public void nt_version_2() {
+ parseCheck("""
+ VERSION "1.2"
+ """);
+ }
+
+ @Test
+ public void nt_version_3() {
+ parseCheck("""
+ VERSION "1.2"
+ VERSION "1.2"
+ """);
+ }
+
@Test
public void nt_only_no_quads() {
parseException(ExFatal.class, "<http://example/x> <http://example/p>
<http://example/s> <http://example/g> .");