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 c2b57a7d48a5f973f588cf9e6b482fb073f19d7f Author: Andy Seaborne <[email protected]> AuthorDate: Mon Apr 6 10:14:53 2026 +0100 GH-3835: N-Triples and N-Quads canonical output format --- .../main/java/org/apache/jena/riot/RDFFormat.java | 7 + .../org/apache/jena/riot/RDFWriterRegistry.java | 78 ++++---- .../org/apache/jena/riot/writer/NQuadsWriter.java | 2 +- .../jena/riot/writer/c14n/DatasetGraphOrdered.java | 194 ++++++++++++++++++++ .../jena/riot/writer/c14n/EscapeStr_C14N.java | 203 +++++++++++++++++++++ .../apache/jena/riot/writer/c14n/GraphOrdered.java | 78 ++++++++ .../jena/riot/writer/c14n/NQuadsWriter_C14N.java | 32 ++++ .../jena/riot/writer/c14n/NTriplesWriter_C14N.java | 32 ++++ .../jena/riot/writer/c14n/NodeFormatter_C14N.java | 104 +++++++++++ .../jena/sparql/core/DatasetGraphCollection.java | 17 +- .../apache/jena/sparql/core/DatasetGraphQuads.java | 3 +- .../java/org/apache/jena/arq/ARQTestSuite.java | 2 +- .../apache/jena/arq/junit/riot/RiotC14NTest.java | 95 ++++++---- .../apache/jena/arq/junit/riot/VocabLangRDF.java | 8 +- .../jena/arq/junit/textrunner/TextTestRunner.java | 6 +- .../riot/{Scripts_c14n.java => Scripts_C14N.java} | 8 +- .../jena/riot/Scripts_RIOT_rdf_tests_std.java | 2 +- .../main/java/org/apache/jena/atlas/lib/Bytes.java | 70 +++---- 18 files changed, 804 insertions(+), 137 deletions(-) diff --git a/jena-arq/src/main/java/org/apache/jena/riot/RDFFormat.java b/jena-arq/src/main/java/org/apache/jena/riot/RDFFormat.java index 35d6ef0ecd..ff98e61ab6 100644 --- a/jena-arq/src/main/java/org/apache/jena/riot/RDFFormat.java +++ b/jena-arq/src/main/java/org/apache/jena/riot/RDFFormat.java @@ -46,6 +46,9 @@ public class RDFFormat { /** Variant for RDF Thrift using values */ public static final RDFFormatVariant ValueEncoding = new RDFFormatVariant("Value") ; + /** Variant for RDF Canonicalization output (N-Triples and N-Quads) */ + public static final RDFFormatVariant CANONICAL = new RDFFormatVariant("canonical"); + /** Turtle - pretty form */ public static final RDFFormat TURTLE_PRETTY = new RDFFormat(Lang.TURTLE, PRETTY) ; /** Turtle - default form */ @@ -69,6 +72,8 @@ public class RDFFormat { public static final RDFFormat NTRIPLES_ASCII = new RDFFormat(Lang.NTRIPLES, ASCII) ; /** N-Triples in UTF-8 with short blank node identifiers */ public static final RDFFormat NTRIPLES_PRETTY = new RDFFormat(Lang.NTRIPLES, PRETTY) ; + /** N-Triples in UTF-8 and canonical form. */ + public static final RDFFormat NTRIPLES_C14N = new RDFFormat(Lang.NTRIPLES, CANONICAL) ; /** N-Quads in UTF-8 */ public static final RDFFormat NQUADS_UTF8 = new RDFFormat(Lang.NQUADS, UTF8) ; @@ -80,6 +85,8 @@ public class RDFFormat { public static final RDFFormat NQUADS_ASCII = new RDFFormat(Lang.NQUADS, ASCII) ; /** N-Quads in UTF-8 with short blank node identifiers */ public static final RDFFormat NQUADS_PRETTY = new RDFFormat(Lang.NTRIPLES, PRETTY) ; + /** N-Quads in UTF-8 and canonical form. */ + public static final RDFFormat NQUADS_C14N = new RDFFormat(Lang.NTRIPLES, CANONICAL) ; /** TriG - pretty form */ public static final RDFFormat TRIG_PRETTY = new RDFFormat(Lang.TRIG, PRETTY) ; diff --git a/jena-arq/src/main/java/org/apache/jena/riot/RDFWriterRegistry.java b/jena-arq/src/main/java/org/apache/jena/riot/RDFWriterRegistry.java index 1ccbc3d3bb..260207c795 100644 --- a/jena-arq/src/main/java/org/apache/jena/riot/RDFWriterRegistry.java +++ b/jena-arq/src/main/java/org/apache/jena/riot/RDFWriterRegistry.java @@ -31,6 +31,8 @@ import org.apache.jena.riot.system.StreamRDFWriter; import org.apache.jena.riot.thrift.WriterDatasetThrift; import org.apache.jena.riot.thrift.WriterGraphThrift; import org.apache.jena.riot.writer.*; +import org.apache.jena.riot.writer.c14n.NQuadsWriter_C14N; +import org.apache.jena.riot.writer.c14n.NTriplesWriter_C14N; import org.apache.jena.sys.JenaSystem; /** @@ -80,6 +82,8 @@ public class RDFWriterRegistry return new NTriplesWriter(CharSpace.ASCII); if ( Objects.equals(RDFFormat.NTRIPLES_PRETTY, serialization) ) return new NTriplesWriterPretty(); + if ( Objects.equals(RDFFormat.NTRIPLES_C14N, serialization) ) + return new NTriplesWriter_C14N(); if ( Objects.equals(RDFFormat.RDFJSON, serialization) ) return new RDFJSONWriter(); @@ -112,6 +116,8 @@ public class RDFWriterRegistry return new NQuadsWriter(CharSpace.ASCII); if ( Objects.equals(RDFFormat.NQUADS_PRETTY, serialization) ) return new NQuadsWriterPretty(); + if ( Objects.equals(RDFFormat.NQUADS_C14N, serialization) ) + return new NQuadsWriter_C14N(); if ( Objects.equals(RDFFormat.RDFNULL, serialization) ) return NullWriter.factory.create(RDFFormat.RDFNULL); @@ -173,61 +179,63 @@ public class RDFWriterRegistry register(RDFFormat.NTRIPLES, wgfactory); register(RDFFormat.NTRIPLES_ASCII, wgfactory); register(RDFFormat.NTRIPLES_PRETTY, wgfactory); + register(RDFFormat.NTRIPLES_C14N, wgfactory); // JSON-LD 1.1 - register(RDFFormat.JSONLD11, wgJsonldFactory11); - register(RDFFormat.JSONLD11_PRETTY, wgJsonldFactory11); - register(RDFFormat.JSONLD11_PLAIN, wgJsonldFactory11); - register(RDFFormat.JSONLD11_FLAT, wgJsonldFactory11); + register(RDFFormat.JSONLD11, wgJsonldFactory11); + register(RDFFormat.JSONLD11_PRETTY, wgJsonldFactory11); + register(RDFFormat.JSONLD11_PLAIN, wgJsonldFactory11); + register(RDFFormat.JSONLD11_FLAT, wgJsonldFactory11); - register(RDFFormat.JSONLD11, wdsJsonldFactory11); - register(RDFFormat.JSONLD11_PRETTY, wdsJsonldFactory11); - register(RDFFormat.JSONLD11_PLAIN, wdsJsonldFactory11); - register(RDFFormat.JSONLD11_FLAT, wdsJsonldFactory11); + register(RDFFormat.JSONLD11, wdsJsonldFactory11); + register(RDFFormat.JSONLD11_PRETTY, wdsJsonldFactory11); + register(RDFFormat.JSONLD11_PLAIN, wdsJsonldFactory11); + register(RDFFormat.JSONLD11_FLAT, wdsJsonldFactory11); // JSON-LD System defaults. - register(RDFFormat.JSONLD, jsonldWriterGraphDefault); - register(RDFFormat.JSONLD_PRETTY, jsonldWriterGraphDefault); - register(RDFFormat.JSONLD_PLAIN, jsonldWriterGraphDefault); - register(RDFFormat.JSONLD_FLAT, jsonldWriterGraphDefault); + register(RDFFormat.JSONLD, jsonldWriterGraphDefault); + register(RDFFormat.JSONLD_PRETTY, jsonldWriterGraphDefault); + register(RDFFormat.JSONLD_PLAIN, jsonldWriterGraphDefault); + register(RDFFormat.JSONLD_FLAT, jsonldWriterGraphDefault); - register(RDFFormat.JSONLD, jsonldWriterDatasetDefault); - register(RDFFormat.JSONLD_PRETTY, jsonldWriterDatasetDefault); - register(RDFFormat.JSONLD_PLAIN, jsonldWriterDatasetDefault); - register(RDFFormat.JSONLD_FLAT, jsonldWriterDatasetDefault); + register(RDFFormat.JSONLD, jsonldWriterDatasetDefault); + register(RDFFormat.JSONLD_PRETTY, jsonldWriterDatasetDefault); + register(RDFFormat.JSONLD_PLAIN, jsonldWriterDatasetDefault); + register(RDFFormat.JSONLD_FLAT, jsonldWriterDatasetDefault); - register(RDFFormat.RDFJSON, wgfactory); + register(RDFFormat.RDFJSON, wgfactory); - register(RDFFormat.RDFXML_PRETTY, wgfactory); - register(RDFFormat.RDFXML_PLAIN, wgfactory); + register(RDFFormat.RDFXML_PRETTY, wgfactory); + register(RDFFormat.RDFXML_PLAIN, wgfactory); // Graphs in a quad format. - register(RDFFormat.TRIG_PRETTY, wgfactory); - register(RDFFormat.TRIG_BLOCKS, wgfactory); - register(RDFFormat.TRIG_FLAT, wgfactory); - register(RDFFormat.TRIG_LONG, wgfactory); + register(RDFFormat.TRIG_PRETTY, wgfactory); + register(RDFFormat.TRIG_BLOCKS, wgfactory); + register(RDFFormat.TRIG_FLAT, wgfactory); + register(RDFFormat.TRIG_LONG, wgfactory); - register(RDFFormat.NQUADS, wgfactory); - register(RDFFormat.NQUADS_ASCII, wgfactory); - register(RDFFormat.NQUADS_PRETTY, wgfactory); - register(RDFFormat.RDFNULL, wgfactory); + register(RDFFormat.NQUADS, wgfactory); + register(RDFFormat.NQUADS_ASCII, wgfactory); + register(RDFFormat.NQUADS_PRETTY, wgfactory); + register(RDFFormat.NQUADS_C14N, wgfactory); register(RDFFormat.RDF_PROTO, wgProtoFactory); register(RDFFormat.RDF_PROTO_VALUES, wgProtoFactory); register(RDFFormat.RDF_THRIFT, wgThriftFactory); register(RDFFormat.RDF_THRIFT_VALUES, wgThriftFactory); - register(RDFFormat.TRIX, wgTriXFactory); + register(RDFFormat.TRIX, wgTriXFactory); + register(RDFFormat.RDFNULL, wgfactory); // Writer factories - datasets. - register(RDFFormat.TRIG_PRETTY, wdsfactory); - register(RDFFormat.TRIG_BLOCKS, wdsfactory); - register(RDFFormat.TRIG_FLAT, wdsfactory); + register(RDFFormat.TRIG_PRETTY, wdsfactory); + register(RDFFormat.TRIG_BLOCKS, wdsfactory); + register(RDFFormat.TRIG_FLAT, wdsfactory); - register(RDFFormat.NQUADS, wdsfactory); - register(RDFFormat.NQUADS_ASCII, wdsfactory); - register(RDFFormat.RDFNULL, wdsfactory); + register(RDFFormat.NQUADS, wdsfactory); + register(RDFFormat.NQUADS_ASCII, wdsfactory); + register(RDFFormat.NQUADS_C14N, wdsfactory); register(RDFFormat.RDF_PROTO, wdsProtoFactory); register(RDFFormat.RDF_PROTO_VALUES, wdsProtoFactory); @@ -235,6 +243,8 @@ public class RDFWriterRegistry register(RDFFormat.RDF_THRIFT_VALUES, wdsThriftFactory); register(RDFFormat.TRIX, wdsTriXFactory); + register(RDFFormat.RDFNULL, wdsfactory); + } // ---- Compatibility diff --git a/jena-arq/src/main/java/org/apache/jena/riot/writer/NQuadsWriter.java b/jena-arq/src/main/java/org/apache/jena/riot/writer/NQuadsWriter.java index 6e9abd6ffe..96352ee16d 100644 --- a/jena-arq/src/main/java/org/apache/jena/riot/writer/NQuadsWriter.java +++ b/jena-arq/src/main/java/org/apache/jena/riot/writer/NQuadsWriter.java @@ -69,7 +69,7 @@ public class NQuadsWriter extends WriterDatasetRIOTBase { s.finish(); } - private final CharSpace charSpace; + protected final CharSpace charSpace; public NQuadsWriter() { this(CharSpace.UTF8); diff --git a/jena-arq/src/main/java/org/apache/jena/riot/writer/c14n/DatasetGraphOrdered.java b/jena-arq/src/main/java/org/apache/jena/riot/writer/c14n/DatasetGraphOrdered.java new file mode 100644 index 0000000000..4051d5c7b2 --- /dev/null +++ b/jena-arq/src/main/java/org/apache/jena/riot/writer/c14n/DatasetGraphOrdered.java @@ -0,0 +1,194 @@ +/* + * 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 + * + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.apache.jena.riot.writer.c14n; + +import java.util.Iterator; +import java.util.LinkedHashSet; + +import org.apache.jena.atlas.iterator.Iter; +import org.apache.jena.graph.Graph; +import org.apache.jena.graph.Node; +import org.apache.jena.query.ReadWrite; +import org.apache.jena.query.TxnType; +import org.apache.jena.riot.system.PrefixMap; +import org.apache.jena.riot.system.PrefixMapFactory; +import org.apache.jena.sparql.core.*; + +/** + * A simple dataset implementation that preserves the order of quads. + * {@link DatasetGraph#find()} will return in insertion order. + */ +public class DatasetGraphOrdered extends DatasetGraphQuads { + + private LinkedHashSet<Quad> quads = new LinkedHashSet<>(); + private PrefixMap prefixMap = PrefixMapFactory.create(); + + @Override + public PrefixMap prefixes() { + return prefixMap; + } + + @Override + public Iterator<Quad> find() { + return quads.iterator(); + } + + @Override + public Iterator<Quad> find(Node g, Node s, Node p, Node o) { + Iterator<Quad> iterator = Iter.filter(quads.iterator(), quad -> matches(quad, g, s, p, o)); + return iterator; + } + + @Override + public Iterator<Quad> findNG(Node g, Node s, Node p, Node o) { + Iterator<Quad> iterator = Iter.filter(quads.iterator(), + quad -> (matches(quad, g, s, p, o) && ! Quad.isDefaultGraph(g))); + return iterator; + } + + @Override + public void add(Quad quad) { + quads.add(quad); + } + + @Override + public void delete(Quad quad) { + quads.remove(quad); + } + + @Override + public Graph getDefaultGraph() { + return GraphView.createDefaultGraph(this); + } + + @Override + public Graph getGraph(Node graphNode) { + return GraphView.createNamedGraph(this, graphNode); + } + + private static boolean matches(Quad quadData, Node g, Node s, Node p, Node o) { + return Match.match(quadData, g, s, p, o); + } + + // ---- + private final Transactional txn = TransactionalLock.createMRSW(); + private final Transactional txn() { + return txn; + } + + @Override + public void begin() { + txn().begin(); + } + + @Override + public void begin(TxnType txnType) { + txn().begin(txnType); + } + + @Override + public void begin(ReadWrite mode) { + txn().begin(mode); + } + + @Override + public boolean promote(Promote txnType) { + return txn().promote(txnType); + } + + @Override + public void commit() { + txn().commit(); + } + + @Override + public void abort() { + txn().abort(); + } + + @Override + public boolean isInTransaction() { + return txn().isInTransaction(); + } + + @Override + public void end() { + txn().end(); + } + + @Override + public ReadWrite transactionMode() { + return txn().transactionMode(); + } + + @Override + public TxnType transactionType() { + return txn().transactionType(); + } + + @Override + public boolean supportsTransactions() { + return true; + } + + @Override + public boolean supportsTransactionAbort() { + return false; + } + // ---- + + // Secondary indexes? +// +// @Override +// public void performAdd( Triple t ) { +// triples.add(t); +// } +// +// @Override +// public void performDelete( Triple t ) { +// triples.remove(t); +// } +// +// @Override +// public TransactionHandler getTransactionHandler() { +// return new TransactionHandlerNull(); +// } +// +// @Override +// public ExtendedIterator<Triple> find() { +// return WrappedIterator.create(triples.iterator()); +// } +// +// @Override +// protected ExtendedIterator<Triple> graphBaseFind(Triple triplePattern) { +// Iterator<Triple> iterator = Iter.filter(triples.iterator(), +// triple->matches(triple, triplePattern)); +// return WrappedIterator.create(iterator); +// } +// +// private static boolean matches(Triple tripleData, Triple triplePattern) { +// return Match.match(tripleData, +// triplePattern.getSubject(), +// triplePattern.getPredicate(), +// triplePattern.getObject()); +// } +} diff --git a/jena-arq/src/main/java/org/apache/jena/riot/writer/c14n/EscapeStr_C14N.java b/jena-arq/src/main/java/org/apache/jena/riot/writer/c14n/EscapeStr_C14N.java new file mode 100644 index 0000000000..4e4d090878 --- /dev/null +++ b/jena-arq/src/main/java/org/apache/jena/riot/writer/c14n/EscapeStr_C14N.java @@ -0,0 +1,203 @@ +/* + * 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 + * + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.apache.jena.riot.writer.c14n; + +import static org.apache.jena.riot.system.RiotChars.range; + +import org.apache.jena.atlas.AtlasException ; +import org.apache.jena.atlas.io.AWriter ; +import org.apache.jena.atlas.io.OutputUtils ; +import org.apache.jena.atlas.lib.CharSpace; +import org.apache.jena.atlas.lib.Chars; +import org.apache.jena.util.XML11Char; + +/** String escape utilities */ +public class EscapeStr_C14N +{ + /** String escape, with quote escaping, including option for multi-line 3 quote form. */ + public static void stringEsc(AWriter out, String s, char quoteChar) { + stringEsc(out, s, quoteChar, true, CharSpace.UTF8); + } + +// /** String escape, with quote escaping, including option for multi-line 3 quote form. */ +// public static void stringEsc(AWriter out, String s, char quoteChar, boolean singleLineString) { +// stringEsc(out, s, quoteChar, singleLineString, CharSpace.UTF8); +// } + + public static void stringEsc(AWriter out, String s, char quoteChar, boolean singleLineString, CharSpace charSpace) { + boolean ascii = ( CharSpace.ASCII == charSpace ) ; + int len = s.length() ; + int quotesInARow = 0 ; + + for (int i = 0; i < len; i++) { + char c = s.charAt(i); + // \\ Escape always possible. + if (c == '\\') { + out.print('\\') ; + out.print(c) ; + continue ; + } + + // Surrogates - print raw so that UTF-8 is generated. + // XML 1.1 includes [#x10000-#x10FFFF] + if ( false ) { + // With checking which should not be necessary. + if ( Character.isHighSurrogate(c) ) { + // Surrogates : value = 0x10000 + (H − 0xD800) × 0x400 + (L − 0xDC00) + // i.e. 0x10000 + (H − 0xD800) << 10 + (L − 0xDC00) + // i.e. 1024 "high" surrogates (D800–DBFF) and 1024 "low" surrogates (DC00–DFFF) + // making 1,048,576 values (2^20) from 0x10000 (0x400 is 1024 = 2^10) + + // But AWriter does not write ints + // s.codePointAt(i); + + // If we want our own checking messages. + i++; + if (i >= len ) + throw new AtlasException("High surrogate at end of string"); + char c2 = s.charAt(i); + if ( !Character.isLowSurrogate(c2) ) + throw new AtlasException("High surrogate not followed by low surrogate"); + out.write(c); + out.write(c2); + continue; + } + if ( Character.isLowSurrogate(c) ) + throw new AtlasException("Low surrogate not following a high surrogate"); + } + + if ( ! singleLineString ) { + // Multiline string. + if ( c == quoteChar ) { + quotesInARow++ ; + if ( (quotesInARow == 3) || (!singleLineString && (i == len - 1)) ) { + // Always quote the final character for multiline use + // otherwise it will run into the wrapping 3 quotes. + out.print("\\"); + out.print(quoteChar); + quotesInARow = 0; + continue; + } + } else { + quotesInARow = 0 ; + } + } else { + // Single line. + if ( c == quoteChar ) { + out.print("\\"); out.print(c) ; continue ; + } + switch(c) { + // x08 - BS - Backspace + // x09 - HT - Horizontal tab + // x0A - LF - Line feed = NL - newline + // NOT x0B - VT - Vertical tab + // x0C - FF - Form Feed + // x0D - CR + case '\b': out.print("\\b"); continue; + case '\t': out.print("\\t"); continue; + case '\n': out.print("\\n"); continue; + case '\f': out.print("\\f"); continue; + case '\r': out.print("\\r"); continue; + default: // Drop through + } + } + + if ( ascii ) { + writeCharAsASCII(out, c) ; + continue; + } + +// if ( c == '\uFFFD' ) { +// // Unicode replacement character: write as \-u escape +// // The text tokenizer raises warnings on raw U+FFFD. A replacement character is generated +// // if a decoding error occurs (e.g. ISO-8859-1 passed into UTF-8); there is no literal U+FFFD +// // in the original input. Written as a unicode escape is not treated as a warning. +// out.print("\\uFFFD"); +// continue; +// } + + // XML11Char.isXML11Valid(c); + // [2] Char ::= [#x1-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF] + + // N-Triples/ N-quads canonical form. + // """ + // Characters in the range from U+0000 to U+0007, VT, characters in the range from U+000E to U+001F, DEL, + // and characters not matching the Char production from [XML11] MUST be represented by UCHAR using a lowercase \ u with 4 HEXes. + // """ + + // Surrogates would be XML11Char.isXML11Invalid, they get printed as \-u + // We want to pass then raw to the java->UTF-8 processor. + if ( c <= 0x07 || c == Chars.VT || range(c, 0x0E , 0x1F ) || c == Chars.DEL || XML11Char.isXML11Invalid(c)) { + + if ( ! Character.isSurrogate(c) ) { + // Only 4 hex here (the Java string would have had surrogates pairs). + writeUnicodeEscape(out, c); + continue; + } + } + + // Normal case! + out.print(c); + } + } + + // Choose between \-U 8 hex and \-u 4 hex. + private static void writeUnicodeEscape(AWriter out, int c) { + if ( c <= 0xFFFF ) + writeUnicodeEscape4(out, c); + else + writeUnicodeEscape8(out, c); + } + + private static void writeUnicodeEscape4(AWriter out, int c) { + out.print("\\u") ; + OutputUtils.printHex(out, c, 4) ; + } + + private static void writeUnicodeEscape8(AWriter out, int c) { + out.print("\\U"); + OutputUtils.printHex(out, c, 8); + } + + /** Write a string with Unicode to ASCII conversion using \-u escapes */ + public static void writeASCII(AWriter out, String s) { + int len = s.length() ; + for (int i = 0; i < len; i++) { + char c = s.charAt(i); + writeCharAsASCII(out, c); + } + } + + /** Write a character with Unicode to ASCII conversion using \-u escapes */ + public static void writeCharAsASCII(AWriter out, char c) { + if ( c >= 32 && c < 127 ) + out.print(c); + else { + // Outside the charset range. + // Does not cover beyond 16 bits codepoints directly + // (i.e. \U escapes) but Java keeps these as surrogate + // pairs and will print as characters + out.print("\\u") ; + OutputUtils.printHex(out, c, 4) ; + } + } +} \ No newline at end of file diff --git a/jena-arq/src/main/java/org/apache/jena/riot/writer/c14n/GraphOrdered.java b/jena-arq/src/main/java/org/apache/jena/riot/writer/c14n/GraphOrdered.java new file mode 100644 index 0000000000..f8491a00a5 --- /dev/null +++ b/jena-arq/src/main/java/org/apache/jena/riot/writer/c14n/GraphOrdered.java @@ -0,0 +1,78 @@ +/* + * 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 + * + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.apache.jena.riot.writer.c14n; + +import java.util.Iterator; +import java.util.LinkedHashSet; + +import org.apache.jena.atlas.iterator.Iter; +import org.apache.jena.graph.Graph; +import org.apache.jena.graph.TransactionHandler; +import org.apache.jena.graph.Triple; +import org.apache.jena.graph.impl.GraphBase; +import org.apache.jena.sparql.core.Match; +import org.apache.jena.sparql.graph.TransactionHandlerNull; +import org.apache.jena.util.iterator.ExtendedIterator; +import org.apache.jena.util.iterator.WrappedIterator; + +/** + * A simple graph implementation that preserves the order of triples. + * {@link Graph#find()} will return in insertion order. + */ +public class GraphOrdered extends GraphBase { + + private LinkedHashSet<Triple> triples = new LinkedHashSet<>(); + // Secondary indexes? + + @Override + public void performAdd(Triple t) { + triples.add(t); + } + + @Override + public void performDelete(Triple t) { + triples.remove(t); + } + + @Override + public TransactionHandler getTransactionHandler() { + return new TransactionHandlerNull(); + } + + @Override + public ExtendedIterator<Triple> find() { + return WrappedIterator.create(triples.iterator()); + } + + @Override + protected ExtendedIterator<Triple> graphBaseFind(Triple triplePattern) { + Iterator<Triple> iterator = Iter.filter(triples.iterator(), triple->matches(triple, triplePattern)); + return WrappedIterator.create(iterator); + } + + private static boolean matches(Triple tripleData, Triple triplePattern) { + return Match.match(tripleData, + triplePattern.getSubject(), + triplePattern.getPredicate(), + triplePattern.getObject()); + } +} diff --git a/jena-arq/src/main/java/org/apache/jena/riot/writer/c14n/NQuadsWriter_C14N.java b/jena-arq/src/main/java/org/apache/jena/riot/writer/c14n/NQuadsWriter_C14N.java new file mode 100644 index 0000000000..700dde4c59 --- /dev/null +++ b/jena-arq/src/main/java/org/apache/jena/riot/writer/c14n/NQuadsWriter_C14N.java @@ -0,0 +1,32 @@ +/* + * 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 + * + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.apache.jena.riot.writer.c14n; + +import org.apache.jena.riot.out.NodeFormatter; +import org.apache.jena.riot.writer.NQuadsWriter; + +public class NQuadsWriter_C14N extends NQuadsWriter { + @Override + protected NodeFormatter createNodeFormatter() { + return new NodeFormatter_C14N(charSpace); + } +} diff --git a/jena-arq/src/main/java/org/apache/jena/riot/writer/c14n/NTriplesWriter_C14N.java b/jena-arq/src/main/java/org/apache/jena/riot/writer/c14n/NTriplesWriter_C14N.java new file mode 100644 index 0000000000..2894eaa51a --- /dev/null +++ b/jena-arq/src/main/java/org/apache/jena/riot/writer/c14n/NTriplesWriter_C14N.java @@ -0,0 +1,32 @@ +/* + * 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 + * + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.apache.jena.riot.writer.c14n; + +import org.apache.jena.riot.out.NodeFormatter; +import org.apache.jena.riot.writer.NTriplesWriter; + +public class NTriplesWriter_C14N extends NTriplesWriter { + @Override + protected NodeFormatter createNodeFormatter() { + return new NodeFormatter_C14N(charSpace); + } +} diff --git a/jena-arq/src/main/java/org/apache/jena/riot/writer/c14n/NodeFormatter_C14N.java b/jena-arq/src/main/java/org/apache/jena/riot/writer/c14n/NodeFormatter_C14N.java new file mode 100644 index 0000000000..4a1b008759 --- /dev/null +++ b/jena-arq/src/main/java/org/apache/jena/riot/writer/c14n/NodeFormatter_C14N.java @@ -0,0 +1,104 @@ +/* + * 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 + * + * https://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. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.apache.jena.riot.writer.c14n; + +import org.apache.jena.atlas.io.AWriter; +import org.apache.jena.atlas.lib.CharSpace; +import org.apache.jena.atlas.lib.EscapeStr; +import org.apache.jena.riot.out.NodeFormatterBase; +import org.apache.jena.riot.out.quoted.QuotedStringOutput; +import org.apache.jena.riot.out.quoted.QuotedStringOutputNT; +import org.apache.jena.riot.out.quoted.QuotedURI; + +/** Formatting for canonical NTriples/NQuads */ +public class NodeFormatter_C14N extends NodeFormatterBase +{ + private final QuotedStringOutput quotedStringProc; + private final QuotedURI quotedUriProc; + + public NodeFormatter_C14N() { this(CharSpace.UTF8); } + + public NodeFormatter_C14N(CharSpace charSpace) { + quotedStringProc = new QuotedStringOutputNT(charSpace) { + @Override + public void writeStr(AWriter writer, String str) { + // Only " strings in N-Triples/N-Quads + writer.print(getQuoteChar()); + // C14N + EscapeStr_C14N.stringEsc(writer, str, getQuoteChar(), true, charSpace); + writer.print(getQuoteChar()); + } + }; + quotedUriProc = new QuotedURI(charSpace); + } + + @Override + public void formatURI(AWriter w, String uriStr) { + quotedUriProc.writeURI(w, uriStr); + } + + @Override + public void formatVar(AWriter w, String name) { + w.print('?'); + EscapeStr.stringEsc(w, name, false); + } + + @Override + public void formatBNode(AWriter w, String label) { + w.print("_:"); + // C14N : Write label as given. Assumes label is valid. + String lab = label; + w.print(lab); + } + + @Override + public void formatLitString(AWriter w, String lex) { + writeEscaped(w, lex); + } + + private void writeEscaped(AWriter w, String lex) { + quotedStringProc.writeStr(w, lex); + } + + @Override + public void formatLitLang(AWriter w, String lex, String langTag) { + writeEscaped(w, lex); + w.print('@'); + w.print(langTag); + } + + @Override + public void formatLitLangDir(AWriter w, String lex, String langTag, String direction) { + writeEscaped(w, lex); + w.print('@'); + w.print(langTag); + w.print("--"); + w.print(direction); + } + + @Override + public void formatLitDT(AWriter w, String lex, String datatypeURI) { + writeEscaped(w, lex); + w.print("^^"); + formatURI(w, datatypeURI); + } +} diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphCollection.java b/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphCollection.java index 35c10c17c0..56bd86ba87 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphCollection.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphCollection.java @@ -32,9 +32,10 @@ import org.apache.jena.graph.Node ; import org.apache.jena.shared.JenaException ; import org.apache.jena.system.G; -/** Base class for implementations of a DatasetGraph as a set of graphs. +/** + * Base class for implementations of a DatasetGraph as a set of graphs. * This can be a fixed collection or a changeable collection depending - * on the implementation of getDefaultGraph()/getGraph(Node) + * on the implementation of getDefaultGraph()/getGraph(Node) */ public abstract class DatasetGraphCollection extends DatasetGraphBaseFind { @@ -55,13 +56,13 @@ public abstract class DatasetGraphCollection extends DatasetGraphBaseFind throw new JenaException("No such graph: "+quad.getGraph()) ; g.delete(quad.asTriple()) ; } - + @Override protected Iterator<Quad> findInDftGraph(Node s, Node p , Node o) { return G.triples2quadsDftGraph(getDefaultGraph().find(s, p, o)) ; } - + @Override protected Iter<Quad> findInSpecificNamedGraph(Node g, Node s, Node p , Node o) { @@ -78,7 +79,7 @@ public abstract class DatasetGraphCollection extends DatasetGraphBaseFind IteratorConcat<Quad> iter = new IteratorConcat<>() ; // Named graphs - for ( ; gnames.hasNext() ; ) + for ( ; gnames.hasNext() ; ) { Node gn = gnames.next(); Iterator<Quad> qIter = findInSpecificNamedGraph(gn, s, p, o) ; @@ -87,13 +88,13 @@ public abstract class DatasetGraphCollection extends DatasetGraphBaseFind } return iter ; } - + @Override public abstract Iterator<Node> listGraphNodes() ; @Override public void clear() { - // Delete all triples in the default graph + // Delete all triples in the default graph getDefaultGraph().clear() ; // Now remove the named graphs (but don't clear them - they may be shared). List<Node> gnList = Iter.toList(listGraphNodes()) ; @@ -101,7 +102,7 @@ public abstract class DatasetGraphCollection extends DatasetGraphBaseFind removeGraph(gn) ; } } - + protected Graph fetchGraph(Node gn) { if ( Quad.isDefaultGraph(gn) || Objects.equals(gn,Quad.tripleInQuad)) // Not preferred style diff --git a/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphQuads.java b/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphQuads.java index bfd70daadb..f755d4db2e 100644 --- a/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphQuads.java +++ b/jena-arq/src/main/java/org/apache/jena/sparql/core/DatasetGraphQuads.java @@ -27,7 +27,8 @@ import org.apache.jena.graph.Graph; import org.apache.jena.graph.Node ; -/** A DatasetGraph base class for pure quad-centric storage. +/** + * A DatasetGraph base class for pure quad-centric storage. */ public abstract class DatasetGraphQuads extends DatasetGraphBase { diff --git a/jena-arq/src/test/java/org/apache/jena/arq/ARQTestSuite.java b/jena-arq/src/test/java/org/apache/jena/arq/ARQTestSuite.java index 51ab6c0335..36d62b077b 100644 --- a/jena-arq/src/test/java/org/apache/jena/arq/ARQTestSuite.java +++ b/jena-arq/src/test/java/org/apache/jena/arq/ARQTestSuite.java @@ -69,7 +69,7 @@ import org.apache.jena.util.TS_UtilsARQ; Scripts_RIOT_extra.class, Scripts_AltTurtle.class, - Scripts_c14n.class, + Scripts_C14N.class, // ARQ, SPARQL 1.0, SPARQL 1.1, SPARQL 1.2 - main engine, default in-memory dataset. Scripts_SPARQL.class, diff --git a/jena-arq/src/test/java/org/apache/jena/arq/junit/riot/RiotC14NTest.java b/jena-arq/src/test/java/org/apache/jena/arq/junit/riot/RiotC14NTest.java index 2b1d0a9ce2..ff564a6e73 100644 --- a/jena-arq/src/test/java/org/apache/jena/arq/junit/riot/RiotC14NTest.java +++ b/jena-arq/src/test/java/org/apache/jena/arq/junit/riot/RiotC14NTest.java @@ -24,19 +24,26 @@ package org.apache.jena.arq.junit.riot; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.function.Consumer; import org.apache.jena.arq.junit.manifest.AbstractManifestTest; import org.apache.jena.arq.junit.manifest.ManifestEntry; -import org.apache.jena.atlas.io.IO; +import org.apache.jena.atlas.io.IOX; +import org.apache.jena.atlas.lib.Bytes; import org.apache.jena.atlas.lib.IRILib; import org.apache.jena.graph.Graph; import org.apache.jena.riot.*; +import org.apache.jena.riot.lang.LabelToNode; +import org.apache.jena.riot.system.ErrorHandlerFactory; import org.apache.jena.riot.system.StreamRDF; import org.apache.jena.riot.system.StreamRDFLib; +import org.apache.jena.riot.writer.c14n.DatasetGraphOrdered; +import org.apache.jena.riot.writer.c14n.GraphOrdered; import org.apache.jena.sparql.core.DatasetGraph; -import org.apache.jena.sparql.core.DatasetGraphFactory; -import org.apache.jena.sparql.graph.GraphFactory; public class RiotC14NTest extends AbstractManifestTest { @@ -58,11 +65,10 @@ public class RiotC14NTest extends AbstractManifestTest { input = entry.getAction().getURI(); output = positiveTest ? entry.getResult().getURI() : null; - boolean silentWarnings = RiotTestsConfig.allowWarnings(manifestEntry); + boolean silentWarnings = true; //RiotTestsConfig.allowWarnings(manifestEntry); parser = ( baseIRI != null ) ? ParsingStepForTest.parse(input, baseIRI, lang, silentWarnings) : ParsingStepForTest.parse(input, lang, silentWarnings); - } @Override @@ -73,74 +79,89 @@ public class RiotC14NTest extends AbstractManifestTest { run4(); } - public void run3() - { - Graph graph = GraphFactory.createGraphMem(); + public void run3() { + Graph graph = new GraphOrdered(); StreamRDF dest = StreamRDFLib.graph(graph); try { - parser.accept(dest); + RDFParser.create().errorHandler(ErrorHandlerFactory.errorHandlerIgnoreWarnings(null)) + .strict(true).forceLang(lang).base(baseIRI).source(input) + // ****** + .labelToNode(LabelToNode.createUseLabelAsGiven()) + .parse(dest); Lang outLang = RDFLanguages.filenameToLang(output, Lang.NTRIPLES); - // Exactly this string. - String actual = RDFWriter.source(graph).format(RDFFormat.NTRIPLES_UTF8).asString(); - String expected; + // Special writer. NTriplesWriter_C14N / NodeFormatter_C14N / EscapeStr_C14N + ByteArrayOutputStream out = new ByteArrayOutputStream(); + RDFWriter.source(graph).format(RDFFormat.NTRIPLES_C14N).output(out); + + byte[] actual = out.toByteArray(); + byte[] expected; try { expected = readFile(output); } catch (RiotException ex) { fail("Failed to read results: "+ex.getMessage()); return; } - boolean b = expected.equals(actual); + // Compare byte-for-byte + boolean b = Bytes.compare(expected, actual) == 0; if ( !b ) { System.out.println("**** Test: "+manifestEntry.getName()); System.out.println("---- Input"); - String inputString = readFile(input); + byte[] bytes = readFile(input); + String inputString = Bytes.bytes2string(actual); System.out.print(inputString); System.out.println("---- Actual"); - System.out.print(actual); + System.out.print(Bytes.bytes2string(actual)); System.out.println("---- Expected"); - System.out.print(expected); + System.out.print(Bytes.bytes2string(expected)); System.out.println("--------"); } assertTrue(b, "Does not match expected canonical text"); } catch (RiotException ex) { - if ( positiveTest ) - throw ex; + if ( positiveTest ) { + fail(ex.getMessage()); + //throw ex; + } } } - public void run4() - { - DatasetGraph dsg = DatasetGraphFactory.create(); + public void run4() { + DatasetGraph dsg = new DatasetGraphOrdered(); StreamRDF dest = StreamRDFLib.dataset(dsg); try { - parser.accept(dest); + RDFParser.create().errorHandler(ErrorHandlerFactory.errorHandlerIgnoreWarnings(null)) + .strict(true).forceLang(lang).base(baseIRI).source(input) + // ****** + .labelToNode(LabelToNode.createUseLabelAsGiven()) + .parse(dest); - Lang outLang = RDFLanguages.filenameToLang(output, Lang.NQUADS); + Lang outLang = RDFLanguages.filenameToLang(output, Lang.NTRIPLES); - // Exactly this string. - String actual = RDFWriter.source(dsg).format(RDFFormat.NQUADS_UTF8).asString(); + // Special writer. NQuadsWriter_C14N / NodeFormatter_C14N / EscapeStr_C14N + ByteArrayOutputStream out = new ByteArrayOutputStream(); + RDFWriter.source(dsg).format(RDFFormat.NQUADS_C14N).output(out); - String expected; + byte[] actual = out.toByteArray(); + byte[] expected; try { expected = readFile(output); } catch (RiotException ex) { fail("Failed to read results: "+ex.getMessage()); return; } - boolean b = expected.equals(actual); - + boolean b = Bytes.compare(expected, actual) == 0; if ( !b ) { System.out.println("**** Test: "+manifestEntry.getName()); System.out.println("---- Input"); - String inputString = readFile(input); + byte[] bytes = readFile(input); + String inputString = Bytes.bytes2string(actual); System.out.print(inputString); System.out.println("---- Actual"); - System.out.print(actual); + System.out.print(Bytes.bytes2string(actual)); System.out.println("---- Expected"); - System.out.print(expected); + System.out.print(Bytes.bytes2string(expected)); System.out.println("--------"); } assertTrue(b, "Does not match expected canonical text"); @@ -150,9 +171,13 @@ public class RiotC14NTest extends AbstractManifestTest { } } - String readFile(String name) { - if ( name.startsWith("file:") ) - return IO.readWholeFileAsUTF8(IRILib.IRIToFilename(name)); - return IO.readWholeFileAsUTF8(name); + private byte[] readFile(String filename) { + String fn = ( filename.startsWith("file:")) ? IRILib.IRIToFilename(filename) : filename; + Path path = Path.of(fn); + try { + return Files.readAllBytes(path); + } catch (IOException ex) { + throw IOX.exception(ex); + } } } diff --git a/jena-arq/src/test/java/org/apache/jena/arq/junit/riot/VocabLangRDF.java b/jena-arq/src/test/java/org/apache/jena/arq/junit/riot/VocabLangRDF.java index 8bb6fadf3e..0704260fe6 100644 --- a/jena-arq/src/test/java/org/apache/jena/arq/junit/riot/VocabLangRDF.java +++ b/jena-arq/src/test/java/org/apache/jena/arq/junit/riot/VocabLangRDF.java @@ -35,9 +35,11 @@ public class VocabLangRDF /** <p>The namespace of the vocabulary as a string</p> */ public static final String NS = "http://www.w3.org/ns/rdftest#"; - /** <p>The namespace of the vocabulary as a string</p> - * @see #NS */ - public static String getURI() {return NS;} + /** + * The namespace of the vocabulary as a string. + * @see #NS + */ + public static String getURI() { return NS; } /** <p>The namespace of the vocabulary as a resource</p> */ public static final Resource NAMESPACE = m_model.createResource( NS ); diff --git a/jena-arq/src/test/java/org/apache/jena/arq/junit/textrunner/TextTestRunner.java b/jena-arq/src/test/java/org/apache/jena/arq/junit/textrunner/TextTestRunner.java index 084ce7dee0..f02865a481 100644 --- a/jena-arq/src/test/java/org/apache/jena/arq/junit/textrunner/TextTestRunner.java +++ b/jena-arq/src/test/java/org/apache/jena/arq/junit/textrunner/TextTestRunner.java @@ -90,7 +90,7 @@ public class TextTestRunner { if ( produceEarlReport ) { // Build report, no output. - launcher.registerTestExecutionListeners(executionStats); + launcher.registerTestExecutionListeners(executionStats, summaryListener); } else { launcher.registerTestExecutionListeners(executionStats, printExecListener, summaryListener); } @@ -98,11 +98,10 @@ public class TextTestRunner { // Run, which calls the TestFactory which generates the tests from the manifest. launcher.execute(request); - // For skips tests. TestExecutionSummary summary = summaryListener.getSummary(); if ( produceEarlReport ) { - //RDFWriter.source(earlReport.getModel()).format(RDFFormat.TURTLE).output(System.out); + // out.println("Tests skipped: "+summary.getTestsSkippedCount()); EarlReporter.clearEarlReport(); } else { out.println(); @@ -113,7 +112,6 @@ public class TextTestRunner { out.printf("** Failures: %s\n", executionStats.getTestFailures()); out.println(); } - // summary should be null only when producing EARL reports. //summary.printTo if ( summary.getTestsSkippedCount() > 0 ) { out.println("Tests pass: "+executionStats.getTestPasses()); diff --git a/jena-arq/src/test/java/org/apache/jena/riot/Scripts_c14n.java b/jena-arq/src/test/java/org/apache/jena/riot/Scripts_C14N.java similarity index 89% rename from jena-arq/src/test/java/org/apache/jena/riot/Scripts_c14n.java rename to jena-arq/src/test/java/org/apache/jena/riot/Scripts_C14N.java index f317906f9c..0688f6c2cf 100644 --- a/jena-arq/src/test/java/org/apache/jena/riot/Scripts_c14n.java +++ b/jena-arq/src/test/java/org/apache/jena/riot/Scripts_C14N.java @@ -23,7 +23,6 @@ package org.apache.jena.riot; import java.util.stream.Stream; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.DynamicNode; import org.junit.jupiter.api.TestFactory; @@ -32,21 +31,20 @@ import org.apache.jena.arq.TestConsts; import org.apache.jena.arq.junit.Scripts; /** Canonicalization tests - N-triples and N-Quads */ -@Disabled -public class Scripts_c14n { +public class Scripts_C14N { //static final String DIR="testing/rdf-tests-cg/"; // Canonicalization tests @TestFactory - @DisplayName("rdf-tests CG - N-Quads Canonicalization") + @DisplayName("rdf-tests - N-Quads Canonicalization") public Stream<DynamicNode> testFactory_n_quads_c14n() { return Scripts.manifestTestFactory(TestConsts.RDF12_TESTS_DIR+"rdf-n-quads/c14n/manifest.ttl"); } @TestFactory - @DisplayName("rdf-tests CG - N-Triples Canonicalization") + @DisplayName("rdf-tests - N-Triples Canonicalization") public Stream<DynamicNode> testFactory_n_Triples_c14n() { return Scripts.manifestTestFactory(TestConsts.RDF12_TESTS_DIR+"rdf-n-triples/c14n/manifest.ttl"); } diff --git a/jena-arq/src/test/java/org/apache/jena/riot/Scripts_RIOT_rdf_tests_std.java b/jena-arq/src/test/java/org/apache/jena/riot/Scripts_RIOT_rdf_tests_std.java index ee8817cdc3..cea736bd95 100644 --- a/jena-arq/src/test/java/org/apache/jena/riot/Scripts_RIOT_rdf_tests_std.java +++ b/jena-arq/src/test/java/org/apache/jena/riot/Scripts_RIOT_rdf_tests_std.java @@ -29,7 +29,7 @@ import org.apache.jena.arq.TestConsts; import org.apache.jena.arq.junit.Scripts; /** Run the RDF Test CG test suites for RDF syntaxes - * @see Scripts_c14n + * @see Scripts_C14N */ @TestMethodOrder(MethodOrderer.OrderAnnotation.class) public class Scripts_RIOT_rdf_tests_std { diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/Bytes.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/Bytes.java index 3b7be36a33..6c1f841ff3 100644 --- a/jena-base/src/main/java/org/apache/jena/atlas/lib/Bytes.java +++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/Bytes.java @@ -50,40 +50,34 @@ public class Bytes } /** Compare two byte arrays which may be of different lengths */ - public static int compare(byte[] x1, byte[] x2) - { + public static int compare(byte[] x1, byte[] x2) { int n = Math.min(x1.length, x2.length); - for ( int i = 0; i < n; i++ ) - { + for ( int i = 0 ; i < n ; i++ ) { byte b1 = x1[i]; byte b2 = x2[i]; if ( b1 == b2 ) continue; // Treat as unsigned values in the bytes. - return (b1&0xFF) - (b2&0xFF); + return (b1 & 0xFF) - (b2 & 0xFF); } return x1.length - x2.length; } - public static int compareByte(byte b1, byte b2) - { - return (b1&0xFF) - (b2&0xFF); + public static int compareByte(byte b1, byte b2) { + return (b1 & 0xFF) - (b2 & 0xFF); } - public static byte[] copyOf(byte[] bytes) - { + public static byte[] copyOf(byte[] bytes) { return copyOf(bytes, 0, bytes.length); } - public static byte[] copyOf(byte[] bytes, int start) - { - return copyOf(bytes, start, bytes.length-start); + public static byte[] copyOf(byte[] bytes, int start) { + return copyOf(bytes, start, bytes.length - start); } - public static byte[] copyOf(byte[] bytes, int start, int length) - { + public static byte[] copyOf(byte[] bytes, int start, int length) { byte[] newByteArray = new byte[length]; System.arraycopy(bytes, start, newByteArray, 0, length); return newByteArray; @@ -129,8 +123,7 @@ public class Bytes * @param b Byte Array * @param idx Starting point of bytes */ - public static final int getInt(byte[]b, int idx) - { + public static final int getInt(byte[]b, int idx) { return assembleInt(b[idx+0], b[idx+1], b[idx+2], @@ -147,8 +140,7 @@ public class Bytes * @param b Byte Array * @param idx Starting point of bytes */ - public static final long getLong(byte[]b, int idx) - { + public static final long getLong(byte[]b, int idx) { return assembleLong(b[idx+0], b[idx+1], b[idx+2], @@ -157,7 +149,6 @@ public class Bytes b[idx+5], b[idx+6], b[idx+7]); - } /** Put an int into a byte array @@ -172,8 +163,7 @@ public class Bytes * @param b byte array * @param idx starting point */ - public static final void setInt(int x, byte[]b, int idx) - { + public static final void setInt(int x, byte[]b, int idx) { // b[idx+0] = byte3(value); // b[idx+1] = byte2(value); // b[idx+2] = byte1(value); @@ -182,10 +172,8 @@ public class Bytes b[idx+1] = (byte)((x >> 16)&0xFF); b[idx+2] = (byte)((x >> 8)&0xFF); b[idx+3] = (byte)(x &0xFF); - } - /** Put a long into a byte array * @param value The integer * @param b byte array @@ -228,7 +216,7 @@ public class Bytes } /** Make a long order of args -- high to low */ - static private Long assembleLong(byte b7, byte b6, byte b5, byte b4, byte b3, byte b2, byte b1, byte b0) { + static private long assembleLong(byte b7, byte b6, byte b5, byte b4, byte b3, byte b2, byte b1, byte b0) { return ((b7 & 0xFFL) << 56) | ((b6 & 0xFFL) << 48) | ((b5 & 0xFFL) << 40) | @@ -239,10 +227,10 @@ public class Bytes ((b0 & 0xFFL) << 0); } - private static byte byte3(int x) { return (byte)(x >> 24); } - private static byte byte2(int x) { return (byte)(x >> 16); } - private static byte byte1(int x) { return (byte)(x >> 8); } - private static byte byte0(int x) { return (byte)(x >> 0); } +// private static byte byte3(int x) { return (byte)(x >> 24); } +// private static byte byte2(int x) { return (byte)(x >> 16); } +// private static byte byte1(int x) { return (byte)(x >> 8); } +// private static byte byte0(int x) { return (byte)(x >> 0); } /** Return the UTF-8 bytes for a string */ public static byte[] string2bytes(String x) { @@ -337,23 +325,19 @@ public class Bytes } /** Return a hex string representing the byte. */ - public static String asHex(byte b) - { + public static String asHex(byte b) { return asHexUC(b); } - public static String asHexUC(byte b) - { + public static String asHexUC(byte b) { return asHex(b, Chars.hexDigitsUC); } - public static String asHexLC(byte b) - { + public static String asHexLC(byte b) { return asHex(b, Chars.hexDigitsLC); } - private static String asHex(byte b, char[] hexDigits) - { + private static String asHex(byte b, char[] hexDigits) { int hi = (b & 0xF0) >> 4; int lo = b & 0xF; char[] chars = new char[2]; @@ -362,16 +346,14 @@ public class Bytes return new String(chars); } - - public static int hexCharToInt(char c) - { + public static int hexCharToInt(char c) { if ( '0' <= c && c <= '9' ) - return c-'0'; + return c - '0'; else if ( 'A' <= c && c <= 'F' ) - return c-'A'+10; + return c - 'A' + 10; else if ( 'a' <= c && c <= 'f' ) - return c-'a'+10; + return c - 'a' + 10; else - throw new IllegalArgumentException("Bad index char : "+c); + throw new IllegalArgumentException("Bad index char : " + c); } }
