From f56f8b400b18085c8190a81cf3e0148b1ac90f2f Mon Sep 17 00:00:00 2001 From: Florian Kleedorfer Date: Mon, 16 Sep 2024 14:08:18 +0200 Subject: [PATCH 1/4] Feature: Skip double formatting --- README.md | 19 +++++++ .../turtle/formatter/FormattingStyle.java | 3 ++ .../turtle/formatter/TurtleFormatter.java | 54 +++++++++++++------ .../turtle/formatter/TurtleFormatterTest.java | 33 +++++++----- 4 files changed, 78 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index ae9580a..ff40e17 100644 --- a/README.md +++ b/README.md @@ -309,6 +309,23 @@ A [NumberFormat](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/ja `0.####E0` + + + + + +`skipDoubleFormatting` + + + + +Allows for suppressing double formatting + + + + +`false` + @@ -691,6 +708,8 @@ elements in RDF lists. \* Adapted from [EditorConfig](https://editorconfig.org/#file-format-details) ## Release Notes +* 1.2.13: + * Feature: Skip double formatting * 1.2.12: * Bugfix: Handle RDF lists that start with a non-anonymous node * Bugfix: Handle blank node cycles diff --git a/src/main/java/de/atextor/turtle/formatter/FormattingStyle.java b/src/main/java/de/atextor/turtle/formatter/FormattingStyle.java index e931717..3ed5e3d 100644 --- a/src/main/java/de/atextor/turtle/formatter/FormattingStyle.java +++ b/src/main/java/de/atextor/turtle/formatter/FormattingStyle.java @@ -106,6 +106,9 @@ public class FormattingStyle { @Builder.Default public NumberFormat doubleFormat = new DecimalFormat("0.####E0" , DecimalFormatSymbols.getInstance(Locale.US)); + @Builder.Default + public boolean skipDoubleFormatting = true; + @Builder.Default public EndOfLineStyle endOfLine = EndOfLineStyle.LF; diff --git a/src/main/java/de/atextor/turtle/formatter/TurtleFormatter.java b/src/main/java/de/atextor/turtle/formatter/TurtleFormatter.java index 21da9ff..e9d2dd3 100644 --- a/src/main/java/de/atextor/turtle/formatter/TurtleFormatter.java +++ b/src/main/java/de/atextor/turtle/formatter/TurtleFormatter.java @@ -31,6 +31,9 @@ import java.io.IOException; import java.io.OutputStream; import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; @@ -622,23 +625,28 @@ private State writeUriResource( final Resource resource, final State state ) { } private State writeLiteral( final Literal literal, final State state ) { - if ( literal.getDatatypeURI().equals( XSD.xboolean.getURI() ) ) { - return state.write( literal.getBoolean() ? "true" : "false" ); - } - if ( literal.getDatatypeURI().equals( XSD.xstring.getURI() ) ) { - return state.write( quoteAndEscape( literal ) ); - } - if ( literal.getDatatypeURI().equals( XSD.decimal.getURI() ) ) { - return state.write( literal.getLexicalForm() ); - } - if ( literal.getDatatypeURI().equals( XSD.integer.getURI() ) ) { - return state.write( literal.getValue().toString() ); - } - if ( literal.getDatatypeURI().equals( XSD.xdouble.getURI() ) ) { - return state.write( style.doubleFormat.format( literal.getDouble() ) ); - } - if ( literal.getDatatypeURI().equals( RDF.langString.getURI() ) ) { - return state.write( quoteAndEscape( literal ) + "@" + literal.getLanguage() ); + String datatypeUri = literal.getDatatypeURI(); + if (style.skipDoubleFormatting && datatypeUri.equals(XSD.xdouble.getURI())){ + return state.write(literal.getLexicalForm()); + } else { + if (datatypeUri.equals(XSD.xboolean.getURI())) { + return state.write(literal.getBoolean() ? "true" : "false"); + } + if (datatypeUri.equals(XSD.xstring.getURI())) { + return state.write(quoteAndEscape(literal)); + } + if (datatypeUri.equals(XSD.decimal.getURI())) { + return state.write(literal.getLexicalForm()); + } + if (datatypeUri.equals(XSD.integer.getURI())) { + return state.write(literal.getValue().toString()); + } + if (datatypeUri.equals(XSD.xdouble.getURI())) { + return state.write(style.doubleFormat.format(literal.getDouble())); + } + if (datatypeUri.equals(RDF.langString.getURI())) { + return state.write(quoteAndEscape(literal) + "@" + literal.getLanguage()); + } } final Resource typeResource = ResourceFactory.createResource( literal.getDatatypeURI() ); @@ -952,4 +960,16 @@ public State write( final String content ) { return withLastCharacter( end ).withAlignment( alignment + content.length() ); } } + + public static void main(String[] args) throws IOException { + System.out.println(Arrays.stream(args).collect(Collectors.joining("\n"))); + if (args.length != 1){ + throw new IllegalArgumentException("usage: TurtleFormatter "); + } + String filename = args[0]; + String content = Files.readString(Path.of(filename), StandardCharsets.UTF_8); + final FormattingStyle style = FormattingStyle.builder().alignPredicates(true).alignObjects(true).build(); + final TurtleFormatter formatter = new TurtleFormatter(style); + System.out.println(formatter.applyToContent(content)); + } } diff --git a/src/test/java/de/atextor/turtle/formatter/TurtleFormatterTest.java b/src/test/java/de/atextor/turtle/formatter/TurtleFormatterTest.java index 234fc64..b68558c 100644 --- a/src/test/java/de/atextor/turtle/formatter/TurtleFormatterTest.java +++ b/src/test/java/de/atextor/turtle/formatter/TurtleFormatterTest.java @@ -1,25 +1,13 @@ package de.atextor.turtle.formatter; -import org.apache.jena.atlas.io.AWriter; -import org.apache.jena.atlas.io.IO; -import org.apache.jena.graph.Graph; import org.apache.jena.rdf.model.Model; import org.apache.jena.rdf.model.ModelFactory; import org.apache.jena.rdf.model.Property; import org.apache.jena.rdf.model.RDFNode; import org.apache.jena.rdf.model.Resource; import org.apache.jena.rdf.model.Statement; -import org.apache.jena.riot.Lang; -import org.apache.jena.riot.RDFParser; -import org.apache.jena.riot.lang.LabelToNode; -import org.apache.jena.riot.out.NodeFormatter; -import org.apache.jena.riot.out.NodeFormatterNT; -import org.apache.jena.riot.system.StreamRDF; -import org.apache.jena.riot.system.StreamRDFOps; -import org.apache.jena.riot.writer.StreamWriterTriX; -import org.apache.jena.riot.writer.WriterStreamRDFPlain; +import org.apache.jena.rdf.model.impl.PropertyImpl; import org.apache.jena.vocabulary.RDF; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; @@ -28,7 +16,6 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.InputStream; -import java.io.StringWriter; import java.nio.charset.StandardCharsets; import java.util.List; import java.util.Map; @@ -1032,6 +1019,22 @@ void testBlankNodeTriangleWithBlankNodeTriple(){ } } + @Test + public void testSkipFormattingValueOfPredicate() { + final String modelString = """ + @prefix xsd: . + @prefix ex: . + + ex:something ex:decimalProp 0.0000000006241509074460762607776240980930446 ; + ex:doubleProp 6.241509074460762607776240980930446E-10 ."""; + + final FormattingStyle style = FormattingStyle.builder().skipDoubleFormatting(true).build(); + + final TurtleFormatter formatter = new TurtleFormatter( style ); + final String result = formatter.applyToContent( modelString ); + assertThat(result.trim()).isEqualTo(modelString); + } + private Model modelFromString( final String content ) { final Model model = ModelFactory.createDefaultModel(); final InputStream stream = new ByteArrayInputStream( content.getBytes( StandardCharsets.UTF_8 ) ); @@ -1047,4 +1050,6 @@ private Model prefixModel() { model.setNsPrefix( "abcdef", "http://example.com/abc" ); return model; } + + } From 1cc463a7dd43ce6a8dc6d87b013c9291c7bf0074 Mon Sep 17 00:00:00 2001 From: Florian Kleedorfer Date: Mon, 16 Sep 2024 14:22:50 +0200 Subject: [PATCH 2/4] Add tests defining default behaviour of double formatting --- .../turtle/formatter/TurtleFormatterTest.java | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/test/java/de/atextor/turtle/formatter/TurtleFormatterTest.java b/src/test/java/de/atextor/turtle/formatter/TurtleFormatterTest.java index b68558c..cb3d7f0 100644 --- a/src/test/java/de/atextor/turtle/formatter/TurtleFormatterTest.java +++ b/src/test/java/de/atextor/turtle/formatter/TurtleFormatterTest.java @@ -1035,6 +1035,38 @@ public void testSkipFormattingValueOfPredicate() { assertThat(result.trim()).isEqualTo(modelString); } + @Test + public void testDoubleFormatDefault() { + final String modelString = """ + @prefix xsd: . + @prefix ex: . + + ex:something ex:decimalProp 0.0000000006241509074460762607776240980930446 ; + ex:doubleProp 6.241509074460762607776240980930446E-10 ."""; + + final FormattingStyle style = FormattingStyle.builder().build(); + + final TurtleFormatter formatter = new TurtleFormatter( style ); + final String result = formatter.applyToContent( modelString ); + assertThat(result.trim()).isEqualTo(modelString); + } + + @Test + public void testDoubleFormat() { + final String modelString = """ + @prefix xsd: . + @prefix ex: . + + ex:something ex:decimalProp 0.0000000006241509074460762607776240980930446 ; + ex:doubleProp 6.2415E-10 ."""; + + final FormattingStyle style = FormattingStyle.builder().skipDoubleFormatting(false).build(); + + final TurtleFormatter formatter = new TurtleFormatter( style ); + final String result = formatter.applyToContent( modelString ); + assertThat(result.trim()).isEqualTo(modelString); + } + private Model modelFromString( final String content ) { final Model model = ModelFactory.createDefaultModel(); final InputStream stream = new ByteArrayInputStream( content.getBytes( StandardCharsets.UTF_8 ) ); From b1f6bb03cf7a663f236bc3bbcacb416e657ced9f Mon Sep 17 00:00:00 2001 From: Florian Kleedorfer Date: Mon, 16 Sep 2024 14:44:02 +0200 Subject: [PATCH 3/4] Rename `skipDoubleFormatting` to `enableDoubleFormatting` --- README.md | 6 +++--- .../de/atextor/turtle/formatter/FormattingStyle.java | 2 +- .../de/atextor/turtle/formatter/TurtleFormatter.java | 9 +++++---- .../atextor/turtle/formatter/TurtleFormatterTest.java | 11 +++++------ 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index ff40e17..3775c73 100644 --- a/README.md +++ b/README.md @@ -302,7 +302,7 @@ One of `LATIN1`, `UTF_16_BE`, `UTF_16_LE`, `UTF_8`, `UTF_8_BOM` -A [NumberFormat](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/text/NumberFormat.html) that describes how `xsd:double` literals are formatted +A [NumberFormat](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/text/NumberFormat.html) that describes how `xsd:double` literals are formatted if `enableDoubleFormatting` is `true`. @@ -314,12 +314,12 @@ A [NumberFormat](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/ja -`skipDoubleFormatting` +`enableDoubleFormatting` -Allows for suppressing double formatting +Enables formatting of `xsd:double` values (see `doubleFormat` option) diff --git a/src/main/java/de/atextor/turtle/formatter/FormattingStyle.java b/src/main/java/de/atextor/turtle/formatter/FormattingStyle.java index 3ed5e3d..195ef94 100644 --- a/src/main/java/de/atextor/turtle/formatter/FormattingStyle.java +++ b/src/main/java/de/atextor/turtle/formatter/FormattingStyle.java @@ -107,7 +107,7 @@ public class FormattingStyle { public NumberFormat doubleFormat = new DecimalFormat("0.####E0" , DecimalFormatSymbols.getInstance(Locale.US)); @Builder.Default - public boolean skipDoubleFormatting = true; + public boolean enableDoubleFormatting = false; @Builder.Default public EndOfLineStyle endOfLine = EndOfLineStyle.LF; diff --git a/src/main/java/de/atextor/turtle/formatter/TurtleFormatter.java b/src/main/java/de/atextor/turtle/formatter/TurtleFormatter.java index e9d2dd3..acdb54f 100644 --- a/src/main/java/de/atextor/turtle/formatter/TurtleFormatter.java +++ b/src/main/java/de/atextor/turtle/formatter/TurtleFormatter.java @@ -626,8 +626,12 @@ private State writeUriResource( final Resource resource, final State state ) { private State writeLiteral( final Literal literal, final State state ) { String datatypeUri = literal.getDatatypeURI(); - if (style.skipDoubleFormatting && datatypeUri.equals(XSD.xdouble.getURI())){ + if (datatypeUri.equals(XSD.xdouble.getURI())) { + if (style.enableDoubleFormatting){ + return state.write(style.doubleFormat.format(literal.getDouble())); + } else { return state.write(literal.getLexicalForm()); + } } else { if (datatypeUri.equals(XSD.xboolean.getURI())) { return state.write(literal.getBoolean() ? "true" : "false"); @@ -641,9 +645,6 @@ private State writeLiteral( final Literal literal, final State state ) { if (datatypeUri.equals(XSD.integer.getURI())) { return state.write(literal.getValue().toString()); } - if (datatypeUri.equals(XSD.xdouble.getURI())) { - return state.write(style.doubleFormat.format(literal.getDouble())); - } if (datatypeUri.equals(RDF.langString.getURI())) { return state.write(quoteAndEscape(literal) + "@" + literal.getLanguage()); } diff --git a/src/test/java/de/atextor/turtle/formatter/TurtleFormatterTest.java b/src/test/java/de/atextor/turtle/formatter/TurtleFormatterTest.java index cb3d7f0..f3ce6f8 100644 --- a/src/test/java/de/atextor/turtle/formatter/TurtleFormatterTest.java +++ b/src/test/java/de/atextor/turtle/formatter/TurtleFormatterTest.java @@ -6,7 +6,6 @@ import org.apache.jena.rdf.model.RDFNode; import org.apache.jena.rdf.model.Resource; import org.apache.jena.rdf.model.Statement; -import org.apache.jena.rdf.model.impl.PropertyImpl; import org.apache.jena.vocabulary.RDF; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; @@ -1020,7 +1019,7 @@ void testBlankNodeTriangleWithBlankNodeTriple(){ } @Test - public void testSkipFormattingValueOfPredicate() { + public void testEnableDoubleFormatting() { final String modelString = """ @prefix xsd: . @prefix ex: . @@ -1028,7 +1027,7 @@ public void testSkipFormattingValueOfPredicate() { ex:something ex:decimalProp 0.0000000006241509074460762607776240980930446 ; ex:doubleProp 6.241509074460762607776240980930446E-10 ."""; - final FormattingStyle style = FormattingStyle.builder().skipDoubleFormatting(true).build(); + final FormattingStyle style = FormattingStyle.builder().enableDoubleFormatting(false).build(); final TurtleFormatter formatter = new TurtleFormatter( style ); final String result = formatter.applyToContent( modelString ); @@ -1036,7 +1035,7 @@ public void testSkipFormattingValueOfPredicate() { } @Test - public void testDoubleFormatDefault() { + public void testDoubleFormattingDefault() { final String modelString = """ @prefix xsd: . @prefix ex: . @@ -1052,7 +1051,7 @@ public void testDoubleFormatDefault() { } @Test - public void testDoubleFormat() { + public void testDisableDoubleFormatting() { final String modelString = """ @prefix xsd: . @prefix ex: . @@ -1060,7 +1059,7 @@ public void testDoubleFormat() { ex:something ex:decimalProp 0.0000000006241509074460762607776240980930446 ; ex:doubleProp 6.2415E-10 ."""; - final FormattingStyle style = FormattingStyle.builder().skipDoubleFormatting(false).build(); + final FormattingStyle style = FormattingStyle.builder().enableDoubleFormatting(true).build(); final TurtleFormatter formatter = new TurtleFormatter( style ); final String result = formatter.applyToContent( modelString ); From 64c0cbfe298ea20cca9ed1e6cf4c2f440f66ddf5 Mon Sep 17 00:00:00 2001 From: Florian Kleedorfer Date: Tue, 17 Sep 2024 08:57:41 +0200 Subject: [PATCH 4/4] Apply requested changes - remove `main()` method - simplify if cascad --- .../turtle/formatter/TurtleFormatter.java | 45 +++++++------------ 1 file changed, 16 insertions(+), 29 deletions(-) diff --git a/src/main/java/de/atextor/turtle/formatter/TurtleFormatter.java b/src/main/java/de/atextor/turtle/formatter/TurtleFormatter.java index acdb54f..1a46727 100644 --- a/src/main/java/de/atextor/turtle/formatter/TurtleFormatter.java +++ b/src/main/java/de/atextor/turtle/formatter/TurtleFormatter.java @@ -632,25 +632,24 @@ private State writeLiteral( final Literal literal, final State state ) { } else { return state.write(literal.getLexicalForm()); } - } else { - if (datatypeUri.equals(XSD.xboolean.getURI())) { - return state.write(literal.getBoolean() ? "true" : "false"); - } - if (datatypeUri.equals(XSD.xstring.getURI())) { - return state.write(quoteAndEscape(literal)); - } - if (datatypeUri.equals(XSD.decimal.getURI())) { - return state.write(literal.getLexicalForm()); - } - if (datatypeUri.equals(XSD.integer.getURI())) { - return state.write(literal.getValue().toString()); - } - if (datatypeUri.equals(RDF.langString.getURI())) { - return state.write(quoteAndEscape(literal) + "@" + literal.getLanguage()); - } + } + if (datatypeUri.equals(XSD.xboolean.getURI())) { + return state.write(literal.getBoolean() ? "true" : "false"); + } + if (datatypeUri.equals(XSD.xstring.getURI())) { + return state.write(quoteAndEscape(literal)); + } + if (datatypeUri.equals(XSD.decimal.getURI())) { + return state.write(literal.getLexicalForm()); + } + if (datatypeUri.equals(XSD.integer.getURI())) { + return state.write(literal.getValue().toString()); + } + if (datatypeUri.equals(RDF.langString.getURI())) { + return state.write(quoteAndEscape(literal) + "@" + literal.getLanguage()); } - final Resource typeResource = ResourceFactory.createResource( literal.getDatatypeURI() ); + final Resource typeResource = ResourceFactory.createResource( datatypeUri ); final State literalWritten = state.write( quoteAndEscape( literal ) + "^^" ); return writeUriResource( typeResource, literalWritten ); } @@ -961,16 +960,4 @@ public State write( final String content ) { return withLastCharacter( end ).withAlignment( alignment + content.length() ); } } - - public static void main(String[] args) throws IOException { - System.out.println(Arrays.stream(args).collect(Collectors.joining("\n"))); - if (args.length != 1){ - throw new IllegalArgumentException("usage: TurtleFormatter "); - } - String filename = args[0]; - String content = Files.readString(Path.of(filename), StandardCharsets.UTF_8); - final FormattingStyle style = FormattingStyle.builder().alignPredicates(true).alignObjects(true).build(); - final TurtleFormatter formatter = new TurtleFormatter(style); - System.out.println(formatter.applyToContent(content)); - } }