Merge pull request #764 from afs/test4
JENA-1922: Runners for test sets using W3C test manifests
diff --git a/jena-arq/src/main/java/org/apache/jena/riot/out/NodeFmtLib.java b/jena-arq/src/main/java/org/apache/jena/riot/out/NodeFmtLib.java
index ecc1393..cb0fca6 100644
--- a/jena-arq/src/main/java/org/apache/jena/riot/out/NodeFmtLib.java
+++ b/jena-arq/src/main/java/org/apache/jena/riot/out/NodeFmtLib.java
@@ -40,17 +40,17 @@
* <p>
* Methods <tt>str</tt> generate a reparsable string.
* <p>
- * Methods <tt>displayStr</tt> do not guarantee a reparsable string
- * e.g. may use abbreviations or common prefixes.
+ * Methods <tt>displayStr</tt> do not guarantee a reparsable string
+ * e.g. may use abbreviations or common prefixes.
*/
public class NodeFmtLib
{
// Replaces FmtUtils
// See OutputLangUtils.
// See and use EscapeStr
-
+
private static final NodeFormatter plainFormatter = new NodeFormatterNT();
-
+
private static PrefixMap dftPrefixMap = PrefixMapFactory.create();
static {
PrefixMapping pm = ARQConstants.getGlobalPrefixMap();
@@ -105,9 +105,9 @@
private static String displayStrNodes(Node...nodes) {
StringJoiner sj = new StringJoiner(" ");
- for ( Node n : nodes )
+ for ( Node n : nodes )
sj.add(displayStr(n));
- return sj.toString();
+ return sj.toString();
}
public static void str(IndentedWriter w, Node n) {
@@ -118,6 +118,10 @@
return str(n, prologue.getBaseURI(), prologue.getPrefixMap());
}
+ public static String str(Node n, PrefixMap prefixMap) {
+ return str(n, null, prefixMap);
+ }
+
public static String str(Node n, String base, PrefixMap prefixMap) {
IndentedLineBuffer sw = new IndentedLineBuffer();
serialize(sw, n, base, prefixMap);
@@ -136,21 +140,21 @@
formatter = new NodeFormatterTTL(base, prefixMap);
formatter.format(w, n);
}
-
+
// ---- Blank node labels.
-
+
// Strict N-triples only allows [A-Za-z][A-Za-z0-9]
static char encodeMarkerChar = 'X';
- // These two form a pair to convert bNode labels to a safe (i.e. legal N-triples form) and back agains.
-
+ // These two form a pair to convert bNode labels to a safe (i.e. legal N-triples form) and back agains.
+
// Encoding is:
- // 1 - Add a Letter
+ // 1 - Add a Letter
// 2 - Hexify, as Xnn, anything outside ASCII A-Za-z0-9
// 3 - X is encoded as XX
-
- private static char LabelLeadingLetter = 'B';
-
+
+ private static char LabelLeadingLetter = 'B';
+
public static String encodeBNodeLabel(String label) {
StringBuilder buff = new StringBuilder();
// Must be at least one char and not a digit.
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/algebra/optimize/TransformPathFlattern.java b/jena-arq/src/main/java/org/apache/jena/sparql/algebra/optimize/TransformPathFlattern.java
index 6915233..2d08a71 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/algebra/optimize/TransformPathFlattern.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/algebra/optimize/TransformPathFlattern.java
@@ -29,7 +29,7 @@
* Perform the equivalent of the transactions in the SPARQL 1.1 spec. ARQ
* regards path transformation as an optimization. ARQ does not execute the
* exact transformation as per spec as there are better ways to do it for ARQ.
- * For example,
+ * For example,
* <ul>
* <li>Path seq {@literal ->} BGPs or a (sequence)
* <li>"|" is not expanded into a union.
@@ -38,18 +38,18 @@
public class TransformPathFlattern extends TransformCopy
{
- // This transform is also used so programmtically built queries also get converted.
+ // This transform is also used so programmatically built queries also get converted.
// Need previous BGP for merging? Do as a separate pass (sequence, BGP collapse)
-
+
private PathCompiler pathCompiler ;
public TransformPathFlattern() { this(new PathCompiler()) ; }
-
+
public TransformPathFlattern(PathCompiler pathCompiler)
{
this.pathCompiler = pathCompiler ;
}
-
+
@Override
public Op transform(OpPath opPath)
{
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/path/PathCompiler.java b/jena-arq/src/main/java/org/apache/jena/sparql/path/PathCompiler.java
index ab84fd6..e4d1a50 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/path/PathCompiler.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/path/PathCompiler.java
@@ -23,6 +23,7 @@
import org.apache.jena.sparql.ARQConstants ;
import org.apache.jena.sparql.core.PathBlock ;
import org.apache.jena.sparql.core.TriplePath ;
+import org.apache.jena.sparql.core.Var;
import org.apache.jena.sparql.core.VarAlloc ;
public class PathCompiler
@@ -32,6 +33,9 @@
private static VarAlloc varAlloc = new VarAlloc(ARQConstants.allocPathVariables) ;
+ /** Testing use only. */
+ public static void resetForTest() { varAlloc = new VarAlloc(ARQConstants.allocPathVariables) ; }
+
// Move to AlgebraCompiler and have a per-transaction scoped var generator
// ---- Syntax-based
@@ -95,8 +99,14 @@
{
P_Seq ps = (P_Seq)path ;
Node v = varAlloc.allocVar() ;
- reduce(x, varAlloc, startNode, ps.getLeft(), v) ;
- reduce(x, varAlloc, v, ps.getRight(), endNode) ;
+ if ( Var.isVar(startNode) && ! Var.isVar(endNode) ) {
+ // start at the grounded term.
+ reduce(x, varAlloc, v, ps.getRight(), endNode) ;
+ reduce(x, varAlloc, startNode, ps.getLeft(), v) ;
+ } else {
+ reduce(x, varAlloc, startNode, ps.getLeft(), v) ;
+ reduce(x, varAlloc, v, ps.getRight(), endNode) ;
+ }
return ;
}
diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/sse/lang/SSE_Parser.java b/jena-arq/src/main/java/org/apache/jena/sparql/sse/lang/SSE_Parser.java
index 6eeca0f..5a1f71e 100644
--- a/jena-arq/src/main/java/org/apache/jena/sparql/sse/lang/SSE_Parser.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/sse/lang/SSE_Parser.java
@@ -29,47 +29,35 @@
public class SSE_Parser
{
- public static void term(Reader reader, ParseHandler handler)
- {
- SSE_ParserCore p = new SSE_ParserCore(reader) ;
- p.setHandler(handler) ;
- try
- {
- p.term() ;
- // Checks for EOF
-// //<EOF> test : EOF is always token 0.
-// if ( p.token_source.getNextToken().kind != 0 )
-// throw new SSEParseException("Trailing characters after "+item, item.getLine(), item.getColumn()) ;
- }
- catch (ParseException ex)
- { throw new SSEParseException(ex.getMessage(), ex.currentToken.beginLine, ex.currentToken.beginColumn) ; }
- catch (TokenMgrError tErr)
- {
- // Last valid token : not the same as token error message - but this should not happen
- int col = p.token.endColumn ;
- int line = p.token.endLine ;
- throw new SSEParseException(tErr.getMessage(), line, col) ;
- }
- //catch (JenaException ex) { throw new TurtleParseException(ex.getMessage(), ex) ; }
+ @FunctionalInterface
+ private interface ParserEntry { void entry(SSE_ParserCore parser) throws ParseException; }
+
+ public static void term(Reader reader, ParseHandler handler) {
+ parse$(reader, handler, SSE_ParserCore::term);
}
- public static void parse(Reader reader, ParseHandler handler)
- {
+ public static void parse(Reader reader, ParseHandler handler) {
+ parse$(reader, handler, SSE_ParserCore::parse);
+ }
+
+ private static void parse$(Reader reader, ParseHandler handler, ParserEntry parserStep) {
SSE_ParserCore p = new SSE_ParserCore(reader) ;
p.setHandler(handler) ;
- try
+ try {
+ parserStep.entry(p);
+// Token tok = p.token_source.getNextToken();
+// if ( tok.kind != 0 )
+// throw new SSEParseException("Trailing characters at "+tok, tok.beginLine, tok.beginColumn) ;
+ }
+ catch (ParseException ex)
+ { throw new SSEParseException(ex.getMessage(), ex.currentToken.beginLine, ex.currentToken.beginColumn) ; }
+ catch (TokenMgrError tErr)
{
- p.parse() ;
- }
- catch (ParseException ex)
- { throw new SSEParseException(ex.getMessage(), ex.currentToken.beginLine, ex.currentToken.beginColumn) ; }
- catch (TokenMgrError tErr)
- {
- // Last valid token : not the same as token error message - but this should not happen
- int col = p.token.endColumn ;
- int line = p.token.endLine ;
- throw new SSEParseException(tErr.getMessage(), line, col) ;
- }
- //catch (JenaException ex) { throw new TurtleParseException(ex.getMessage(), ex) ; }
+ // Last valid token : not the same as token error message - but this should not happen
+ int col = p.token.endColumn ;
+ int line = p.token.endLine ;
+ throw new SSEParseException(tErr.getMessage(), line, col) ;
+ }
}
+
}
diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/algebra/optimize/TS_Optimization.java b/jena-arq/src/test/java/org/apache/jena/sparql/algebra/optimize/TS_Optimization.java
index e32bf9d..a6716f5 100644
--- a/jena-arq/src/test/java/org/apache/jena/sparql/algebra/optimize/TS_Optimization.java
+++ b/jena-arq/src/test/java/org/apache/jena/sparql/algebra/optimize/TS_Optimization.java
@@ -31,6 +31,7 @@
, TestTransformFilters.class
, TestTransformFilterEquality.class
, TestTransformFilterPlacement.class
+ , TestTransformPathFlatten.class
, TestTransformMergeBGPs.class
, TestTransformPromoteTableEmpty.class
, TestTransformEliminateAssignments.class
diff --git a/jena-arq/src/test/java/org/apache/jena/sparql/algebra/optimize/TestTransformPathFlatten.java b/jena-arq/src/test/java/org/apache/jena/sparql/algebra/optimize/TestTransformPathFlatten.java
new file mode 100644
index 0000000..6cd77bf
--- /dev/null
+++ b/jena-arq/src/test/java/org/apache/jena/sparql/algebra/optimize/TestTransformPathFlatten.java
@@ -0,0 +1,126 @@
+/*
+ * 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.algebra.optimize;
+
+import static org.apache.jena.atlas.lib.StrUtils.strjoinNL;
+import static org.junit.Assert.assertEquals;
+
+import org.apache.jena.sparql.algebra.Op;
+import org.apache.jena.sparql.algebra.Transformer;
+import org.apache.jena.sparql.algebra.op.OpPath;
+import org.apache.jena.sparql.core.Prologue;
+import org.apache.jena.sparql.core.TriplePath;
+import org.apache.jena.sparql.path.Path;
+import org.apache.jena.sparql.path.PathCompiler;
+import org.apache.jena.sparql.path.PathParser;
+import org.apache.jena.sparql.sse.SSE;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class TestTransformPathFlatten {
+ private static String pre = "(prefix ((: <http://example/>))" ;
+ private static String post = ")" ;
+
+ private static Prologue prologue;
+
+ @BeforeClass public static void beforeClass() {
+ prologue = new Prologue();
+ prologue.getPrefixMapping().setNsPrefix("", "http://example/");
+ }
+
+
+ @Before public void before() {
+ // Reset the variable allocator.
+ PathCompiler.resetForTest();
+ }
+
+ @Test public void pathFlatten_00() {
+ Op op1 = path(":x0", ":p0", ":T0");
+ Op op2 = op("(bgp (triple :x0 :p0 :T0))");
+ test(op1, op2);
+ }
+
+ @Test public void pathFlatten_01() {
+ Op op1 = path(":x1", ":q1/:p1*", ":T1");
+ Op op2 = op("(sequence"
+ ," (bgp (triple :x1 :q1 ??P0))"
+ ," (path ??P0 (path* :p1) :T1))"
+ );
+ test(op1, op2);
+ }
+
+ // JENA-1918 : order of sequence is grounded first.
+ @Test public void pathFlatten_02() {
+ Op op1 = path("?x", ":q1/:p1*", ":T1");
+ Op op2 = op("(sequence"
+ ," (path ??P0 (path* :p1) :T1)"
+ ," (bgp (triple ?x :q1 ??P0)) )"
+ );
+ test(op1, op2);
+ }
+
+ // JENA-1918 : order of sequence is grounded first.
+ @Test public void pathFlatten_10() {
+ Op op1 = path("?x", ":p1{2}", ":T1");
+ Op op2 = op("(bgp"
+ ," (triple ?x :p1 ??P0)"
+ ," (triple ??P0 :p1 :T1)"
+ ,")"
+ );
+ test(op1, op2);
+ }
+
+ @Test public void pathFlatten_11() {
+ Op op1 = path("?x", ":p1{2,}", ":T1");
+ Op op2 = op
+ ("(sequence"
+ ," (path ??P0 (pathN* :p1) :T1)"
+ ," (bgp"
+ ," (triple ?x :p1 ??P1)"
+ ," (triple ??P1 :p1 ??P0)"
+ ," ))");
+ test(op1, op2);
+ }
+
+ private static Op path(String s, String pathStr, String o) {
+ Path path = PathParser.parse(pathStr, prologue);
+ TriplePath tp = new TriplePath(SSE.parseNode(s), path, SSE.parseNode(o));
+ return new OpPath(tp);
+ }
+
+ private static Op op(String...opStr) {
+ String s = strjoinNL(opStr);
+ String input = pre + s + post;
+ return SSE.parseOp(input);
+ }
+
+ private static void test(Op opInput, Op opExpected) {
+ Op op = Transformer.transform(new TransformPathFlattern(), opInput);
+ if ( opExpected == null ) {
+ System.out.print(opInput);
+ System.out.println(" ==>");
+ System.out.print(op);
+ System.out.println();
+ return;
+ }
+
+ assertEquals(opExpected, op);
+ }
+}
diff --git a/jena-base/src/main/java/org/apache/jena/atlas/io/BufferingWriter.java b/jena-base/src/main/java/org/apache/jena/atlas/io/BufferingWriter.java
index 347707a..343c737 100644
--- a/jena-base/src/main/java/org/apache/jena/atlas/io/BufferingWriter.java
+++ b/jena-base/src/main/java/org/apache/jena/atlas/io/BufferingWriter.java
@@ -16,10 +16,10 @@
* limitations under the License.
*/
-package org.apache.jena.atlas.io ;
+package org.apache.jena.atlas.io;
-import java.io.IOException ;
-import java.io.Writer ;
+import java.io.IOException;
+import java.io.Writer;
/**
* A buffering writer. Like BufferedWriter but with no synchronization. A
@@ -30,35 +30,34 @@
* </p>
* This class is not thread safe.
*/
-
public final class BufferingWriter extends Writer {
// Default sizes
- private static final int SIZE = 8 * 1024 ; // Unit size in bytes.
- private static final int BLOB_SIZE = SIZE / 2 ; // Large object size,
- // worse case, bytes
+ private static final int SIZE = 8 * 1024; // Unit size in bytes.
+ private static final int BLOB_SIZE = SIZE / 2; // Large object size, worse case, bytes
// Sizes for this instance
- private final int blockSize ;
- private final int blobSize ;
+ private final int blockSize;
+ private final int blobSize;
- private char[] buffer = new char[SIZE] ;
- private int idx = 0 ;
- private Writer out ;
+ private final char[] buffer;
+ private int idx = 0;
+ private final Writer out;
/** Create a buffering writer */
public BufferingWriter(Writer dest) {
- this(dest, SIZE, BLOB_SIZE) ;
+ this(dest, SIZE, BLOB_SIZE);
}
/** Create a buffering writer */
public BufferingWriter(Writer dest, int size) {
- this(dest, size, size/2) ;
+ this(dest, size, size/2);
}
/** Create a buffering writer */
public BufferingWriter(Writer dest, int size, int blobSize) {
- this.out = dest ;
- this.blockSize = size ;
- this.blobSize = blobSize ;
+ this.out = dest;
+ this.buffer = new char[size];
+ this.blockSize = size;
+ this.blobSize = blobSize;
}
/**
@@ -66,113 +65,113 @@
* @param string Characters
*/
public void output(String string) {
- output(string, 0, string.length()) ;
+ output(string, 0, string.length());
}
-
+
/**
* Output a string
- *
+ *
* @param string Characters
* @param off Starting point in the string
* @param length Length
*/
public void output(String string, int off, int length) {
- boolean largeBlob = (length > blobSize) ;
+ boolean largeBlob = (length > blobSize);
// There is no space or too big
if ( largeBlob || (blockSize - idx) < length )
- flushBuffer() ;
+ flushBuffer();
// If too big, do directly.
if ( largeBlob /* too big */) {
- try { out.write(string, off, length) ; }
- catch (IOException ex) { IO.exception(ex) ; }
- return ;
+ try { out.write(string, off, length); }
+ catch (IOException ex) { IO.exception(ex); }
+ return;
}
- int n = string.length() ;
- string.getChars(off, (n + off), buffer, idx) ;
- idx += n ;
+ int n = string.length();
+ string.getChars(off, (n + off), buffer, idx);
+ idx += n;
}
/** Output an array of characters */
public void output(char chars[]) {
- output(chars, 0, chars.length) ;
+ output(chars, 0, chars.length);
}
/**
* Output an array of characters
- *
+ *
* @param chars Characters
* @param start Start
* @param length Length
*/
public void output(char chars[], int start, int length) {
- boolean largeBlob = (length > blobSize) ;
+ boolean largeBlob = (length > blobSize);
// There is no space or too big
if ( largeBlob || (blockSize - idx) < length )
- flushBuffer() ;
+ flushBuffer();
// If too big, do directly.
if ( largeBlob /* too big */) {
- try { out.write(chars) ; }
- catch (IOException ex) { IO.exception(ex) ; }
- return ;
+ try { out.write(chars, start, length); }
+ catch (IOException ex) { IO.exception(ex); }
+ return;
}
- System.arraycopy(chars, start, buffer, idx, length) ;
- idx += length ;
+ System.arraycopy(chars, start, buffer, idx, length);
+ idx += length;
}
/** Output a single character */
public void output(char ch) {
if ( blockSize == idx )
- flushBuffer() ;
- buffer[idx++] = ch ;
+ flushBuffer();
+ buffer[idx++] = ch;
}
private void flushBuffer() {
if ( idx > 0 ) {
- try { out.write(buffer, 0, idx) ; }
- catch (IOException ex) { IO.exception(ex) ; }
- idx = 0 ;
+ try { out.write(buffer, 0, idx); }
+ catch (IOException ex) { IO.exception(ex); }
+ idx = 0;
}
}
-
+
// ---- Writer
@Override
public void close() {
- flushBuffer() ;
- IO.close(out) ;
+ flushBuffer();
+ IO.close(out);
}
@Override
public void flush() {
- flushBuffer() ;
- IO.flush(out) ;
+ flushBuffer();
+ IO.flush(out);
}
@Override
public void write(char[] cbuf, int off, int len) throws IOException {
- output(cbuf, off, len) ;
+ output(cbuf, off, len);
}
@Override
public void write(char[] cbuf) throws IOException {
- write(cbuf, 0, cbuf.length) ;
+ write(cbuf, 0, cbuf.length);
}
@Override
public void write(String string, int off, int len) throws IOException {
- output(string, off, len) ;
+ output(string, off, len);
}
@Override
public void write(String string) throws IOException {
- output(string, 0, string.length()) ;
+ output(string, 0, string.length());
}
@Override
public void write(int ch) throws IOException {
- output((char)ch) ;
+ output((char)ch);
}
}
diff --git a/jena-base/src/test/java/org/apache/jena/atlas/io/TestBufferingWriter.java b/jena-base/src/test/java/org/apache/jena/atlas/io/TestBufferingWriter.java
index 1414f3e..ba26f6a 100644
--- a/jena-base/src/test/java/org/apache/jena/atlas/io/TestBufferingWriter.java
+++ b/jena-base/src/test/java/org/apache/jena/atlas/io/TestBufferingWriter.java
@@ -95,4 +95,29 @@
String x = string() ;
assertEquals("test", x) ;
}
+
+ @Test // JENA-19219
+ public void write_07() {
+ create(8194, 4098);
+ for (int i = 0; i < 8194;i++) {
+ w.output('a');
+ }
+ w.close();
+ String x = string();
+ assertEquals(x.length(), 8194);
+ }
+
+ @Test // JENA-1920
+ public void write_08() {
+ create(8192, 4096);
+ char[] chars = new char[8192];
+ //define enough to make it a 'large blob'
+ for(int i = 0; i < 5000; i++){
+ chars[i] = '1';
+ }
+ w.output(chars, 0, 5000);
+ w.close();
+ String x = string();
+ assertEquals(5000, x.length());
+ }
}
diff --git a/jena-text/src/main/java/org/apache/jena/query/text/TextIndexTDB1.java b/jena-text/src/main/java/org/apache/jena/query/text/TextIndexTDB1.java
index f713826..f7c6a3d 100644
--- a/jena-text/src/main/java/org/apache/jena/query/text/TextIndexTDB1.java
+++ b/jena-text/src/main/java/org/apache/jena/query/text/TextIndexTDB1.java
@@ -18,7 +18,6 @@
package org.apache.jena.query.text;
-import org.apache.jena.query.text.TextIndex;
import org.apache.jena.tdb.transaction.Transaction;
import org.apache.jena.tdb.transaction.TransactionLifecycle;
@@ -56,5 +55,4 @@
@Override
public void clearupCommitted(Transaction txn) {}
-
}