From d46afa4c0312920d52ba7128e3fde7c55ac8d0e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=CC=88rg=20Prante?= Date: Tue, 19 May 2020 16:06:39 +0200 Subject: [PATCH] add Java named modules, Gradle 6, remove all logging, JUnit 5 --- build.gradle | 212 +++--------------- config/checkstyle/checkstyle.xml | 1 - content-core/build.gradle | 2 +- content-core/src/main/java/module-info.java | 14 ++ .../org/xbib/content/XContentBuilderTest.java | 18 +- .../xbib/content/settings/SettingsTest.java | 8 +- content-csv/src/main/java/module-info.java | 3 + .../java/org/xbib/content/csv/CSVParser.java | 7 +- .../xbib/content/csv/CSVGeneratorTest.java | 3 +- .../org/xbib/content/csv/CSVParserTest.java | 13 +- .../org/xbib/content/csv/TSVParserTest.java | 9 +- .../resources/{log4j2.xml => log4j2-test.xml} | 0 content-json/build.gradle | 7 +- content-json/src/main/java/module-info.java | 8 + .../src/main/java/module-info.java | 4 + content-rdf/build.gradle | 4 +- content-rdf/src/main/java/module-info.java | 17 ++ .../content/rdf/internal/DefaultRdfGraph.java | 8 +- .../content/rdf/internal/DefaultResource.java | 5 +- .../rdf/io/json/JsonContentGenerator.java | 15 +- .../content/rdf/io/nquads/NQuadsParser.java | 7 +- .../rdf/io/nquads/NQuadsSerializer.java | 64 ++---- .../io/ntriple/NTripleContentGenerator.java | 14 +- .../rdf/io/ntriple/NTriplesParser.java | 28 +-- .../rdf/io/ntriple/NTriplesSerializer.java | 49 ++-- .../rdf/io/rdfxml/RdfXmlContentGenerator.java | 138 ++++++------ .../rdf/io/rdfxml/RdfXmlContentParser.java | 13 +- .../xbib/content/rdf/io/sink/QuadSink.java | 11 +- .../rdf/io/sink/RdfContentBuilderSink.java | 115 ++++------ .../xbib/content/rdf/io/sink/TripleSink.java | 12 +- .../rdf/io/turtle/TurtleContentGenerator.java | 18 +- .../rdf/io/turtle/TurtleContentParser.java | 14 +- .../rdf/io/turtle/TurtleSerializer.java | 54 ++--- .../xbib/content/rdf/io/xml/XmlHandler.java | 6 +- .../rdf/IRINamespaceCompactionTest.java | 6 +- .../java/org/xbib/content/rdf/IRITest.java | 21 +- .../content/rdf/RdfXContentGeneratorTest.java | 6 +- .../rdf/RouteRdfXContentBuilderTest.java | 7 +- .../{helper => content/rdf}/StreamTester.java | 18 +- .../content/rdf/internal/BlankNodeTest.java | 6 +- .../content/rdf/internal/LiteralTest.java | 6 +- .../content/rdf/internal/ResourceTest.java | 22 +- .../xbib/content/rdf/internal/TripleTest.java | 6 +- .../content/rdf/io/json/JsonReaderTest.java | 7 +- .../rdf/io/ntriple/NTripleReaderTest.java | 4 +- .../content/rdf/io/ntriple/NTripleTest.java | 7 +- .../rdf/io/rdfxml/EuropeanaEDMReaderTest.java | 10 +- .../rdf/io/rdfxml/GNDRdfXmlReaderTest.java | 10 +- .../rdf/io/rdfxml/RdfXmlReaderTest.java | 10 +- .../rdf/io/rdfxml/VIAFRdfXmlReaderTest.java | 7 +- .../rdf/io/turtle/TurtleConformanceTest.java | 11 +- .../content/rdf/io/turtle/TurtleTest.java | 11 +- .../org/xbib/content/rdf/io/xml/OAITest.java | 18 +- .../content/rdf/io/xml/XmlReaderTest.java | 29 +-- .../rdf/io/xml/XmlResourceWriterTest.java | 9 +- .../xbib/content/rdf/util/MultiMapTest.java | 8 +- .../java/org/xbib/helper/package-info.java | 4 - content-resource/build.gradle | 4 +- .../src/main/java/module-info.java | 5 + .../content/resource/IRINamespaceContext.java | 91 ++++++-- .../content/resource/NamespaceContext.java | 17 ++ content-smile/build.gradle | 4 +- content-smile/src/main/java/module-info.java | 7 + content-xml/build.gradle | 9 +- content-xml/src/main/java/module-info.java | 15 ++ .../content/xml}/XmlNamespaceContext.java | 29 +-- .../content/xml/XmlXContentGenerator.java | 12 +- .../java/org/xbib/content/xml/XmlXParams.java | 32 +-- .../xbib/content/xml/json/JsonSaxAdapter.java | 8 +- .../xbib/content/xml/json/JsonStylesheet.java | 9 +- .../xbib/content/xml/json/JsonXmlReader.java | 10 +- .../content/xml/json/JsonXmlStreamer.java | 11 +- .../content/xml/stream/AbstractXMLEvent.java | 6 +- .../xml/stream/IndentingXMLEventWriter.java | 6 +- .../xml/stream/IndentingXMLStreamWriter.java | 9 +- .../xml/stream/StaxEventXMLReader.java | 5 - ...va => DefaultStylesheetErrorListener.java} | 13 +- .../content/xml/transform/StylesheetPool.java | 6 - .../xml/transform/StylesheetTransformer.java | 2 +- .../transform/TransformerErrorListener.java | 11 +- .../xml/transform/TransformerURIResolver.java | 6 +- .../org/xbib/content/xml/util/ToQName.java | 2 +- .../content/xml/XContentXmlBuilderTest.java | 9 +- .../content/xml/XmlNamespaceContextTest.java | 16 +- .../xbib/content/xml/json/Json2XmlTest.java | 21 +- .../xml/json/StylesheetTransformerTest.java | 9 +- .../xml/util/SaxEventConsumerTest.java | 2 +- .../xbib/content/xml/util/XMLUtilTest.java | 6 +- content-yaml/build.gradle | 6 +- content-yaml/src/main/java/module-info.java | 9 + gradle.properties | 17 +- gradle/compile/java.gradle | 35 +++ gradle/documentation/asciidoc.gradle | 36 +++ gradle/ide/idea.gradle | 13 ++ gradle/publishing/publication.gradle | 64 ++++++ gradle/publishing/sonatype.gradle | 11 + gradle/test/junit5.gradle | 27 +++ gradle/wrapper/gradle-wrapper.jar | Bin 55616 -> 58910 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- gradlew | 31 ++- gradlew.bat | 4 + 101 files changed, 868 insertions(+), 923 deletions(-) create mode 100644 content-core/src/main/java/module-info.java create mode 100644 content-csv/src/main/java/module-info.java rename content-csv/src/test/resources/{log4j2.xml => log4j2-test.xml} (100%) create mode 100644 content-json/src/main/java/module-info.java create mode 100644 content-language/src/main/java/module-info.java create mode 100644 content-rdf/src/main/java/module-info.java rename content-rdf/src/test/java/org/xbib/{helper => content/rdf}/StreamTester.java (65%) delete mode 100644 content-rdf/src/test/java/org/xbib/helper/package-info.java create mode 100644 content-resource/src/main/java/module-info.java create mode 100644 content-resource/src/main/java/org/xbib/content/resource/NamespaceContext.java create mode 100644 content-smile/src/main/java/module-info.java create mode 100644 content-xml/src/main/java/module-info.java rename {content-resource/src/main/java/org/xbib/content/resource => content-xml/src/main/java/org/xbib/content/xml}/XmlNamespaceContext.java (74%) rename content-xml/src/main/java/org/xbib/content/xml/transform/{StylesheetErrorListener.java => DefaultStylesheetErrorListener.java} (59%) create mode 100644 content-yaml/src/main/java/module-info.java create mode 100644 gradle/compile/java.gradle create mode 100644 gradle/documentation/asciidoc.gradle create mode 100644 gradle/ide/idea.gradle create mode 100644 gradle/publishing/publication.gradle create mode 100644 gradle/publishing/sonatype.gradle create mode 100644 gradle/test/junit5.gradle diff --git a/build.gradle b/build.gradle index 379fe31..9d3b235 100644 --- a/build.gradle +++ b/build.gradle @@ -1,192 +1,34 @@ - plugins { - id "org.sonarqube" version "2.8" + id "de.marcphilipp.nexus-publish" version "0.4.0" id "io.codearte.nexus-staging" version "0.21.1" - id "com.github.spotbugs" version "2.0.1" id "org.xbib.gradle.plugin.asciidoctor" version "1.5.6.0.1" } +wrapper { + gradleVersion = "${rootProject.property('gradle.wrapper.version')}" + distributionType = Wrapper.DistributionType.ALL +} + +ext { + user = 'xbib' + name = 'content' + description = 'Content processing library for Java' + inceptionYear = '2016' + url = 'https://github.com/' + user + '/' + name + scmUrl = 'https://github.com/' + user + '/' + name + scmConnection = 'scm:git:git://github.com/' + user + '/' + name + '.git' + scmDeveloperConnection = 'scm:git:ssh://git@github.com:' + user + '/' + name + '.git' + issueManagementSystem = 'Github' + issueManagementUrl = ext.scmUrl + '/issues' + licenseName = 'The Apache License, Version 2.0' + licenseUrl = 'http://www.apache.org/licenses/LICENSE-2.0.txt' +} + subprojects { - - apply plugin: 'java' - apply plugin: 'maven' - apply plugin: 'pmd' - apply plugin: 'checkstyle' - apply plugin: 'com.github.spotbugs' - apply plugin: 'org.xbib.gradle.plugin.asciidoctor' - - repositories { - mavenCentral() - } - - configurations { - asciidoclet - } - - dependencies { - testCompile "org.junit.jupiter:junit-jupiter-api:${project.property('junit.version')}" - testCompile "org.junit.jupiter:junit-jupiter-params:${project.property('junit.version')}" - testCompile "org.junit.jupiter:junit-jupiter-engine:${project.property('junit.version')}" - testCompile "org.junit.vintage:junit-vintage-engine:${project.property('junit.version')}" - testCompile "junit:junit:${project.property('junit4.version')}" - asciidoclet "org.asciidoctor:asciidoclet:${project.property('asciidoclet.version')}" - } - - compileJava { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 - } - - tasks.withType(JavaCompile) { - options.compilerArgs << "-Xlint:all" - } - - jar { - manifest { - attributes('Implementation-Version': project.version) - } - } - - test { - useJUnitPlatform() - failFast = false - testLogging { - events 'STARTED', 'PASSED', 'FAILED', 'SKIPPED' - } - afterSuite { desc, result -> - if (!desc.parent) { - println "\nTest result: ${result.resultType}" - println "Test summary: ${result.testCount} tests, " + - "${result.successfulTestCount} succeeded, " + - "${result.failedTestCount} failed, " + - "${result.skippedTestCount} skipped" - } - } - } - - clean { - delete 'out' - } - - task sourcesJar(type: Jar, dependsOn: classes) { - classifier 'sources' - from sourceSets.main.allSource - } - - task javadocJar(type: Jar, dependsOn: javadoc) { - classifier 'javadoc' - } - - artifacts { - archives sourcesJar, javadocJar - } - - tasks.withType(Checkstyle) { - ignoreFailures = true - reports { - xml.enabled = true - html.enabled = true - } - } - spotbugs { - effort = "max" - reportLevel = "low" - //includeFilter = file("findbugs-exclude.xml") - } - - tasks.withType(com.github.spotbugs.SpotBugsTask) { - ignoreFailures = true - reports { - xml.enabled = false - html.enabled = true - } - } - - tasks.withType(Pmd) { - ignoreFailures = true - reports { - xml.enabled = true - html.enabled = true - } - } - - checkstyle { - configFile = rootProject.file('config/checkstyle/checkstyle.xml') - ignoreFailures = true - showViolations = true - } - - sonarqube { - properties { - property "sonar.projectName", "${project.group} ${project.name}" - property "sonar.sourceEncoding", "UTF-8" - property "sonar.tests", "src/test/java" - property "sonar.scm.provider", "git" - property "sonar.junit.reportsPath", "build/test-results/test/" - } - } - - ext { - projectDescription = 'Content processing library for Java' - scmUrl = 'https://github.com/xbib/content' - scmConnection = 'scm:git:git://github.com/xbib/content.git' - scmDeveloperConnection = 'scm:git:git://github.com/xbib/content.git' - } - - task sonatypeUpload(type: Upload, dependsOn: build) { - group = 'publish' - configuration = configurations.archives - uploadDescriptor = true - repositories { - if (project.hasProperty('ossrhUsername')) { - mavenDeployer { - beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) } - repository(url: uri(ossrhReleaseUrl)) { - authentication(userName: ossrhUsername, password: ossrhPassword) - } - snapshotRepository(url: uri(ossrhSnapshotUrl)) { - authentication(userName: ossrhUsername, password: ossrhPassword) - } - pom.project { - groupId project.group - artifactId project.name - version project.version - name project.name - description projectDescription - packaging 'jar' - inceptionYear '2016' - url scmUrl - organization { - name 'xbib' - url 'http://xbib.org' - } - developers { - developer { - id 'xbib' - name 'Jörg Prante' - email 'joergprante@gmail.com' - url 'https://github.com/jprante' - } - } - scm { - url scmUrl - connection scmConnection - developerConnection scmDeveloperConnection - } - licenses { - license { - name 'The Apache License, Version 2.0' - url 'http://www.apache.org/licenses/LICENSE-2.0.txt' - } - } - } - } - } - } - } -} - -nexusStaging { - packageGroup = "org.xbib" - //stagingProfileId = "org.xbib" + apply plugin: 'java-library' + apply from: rootProject.file('gradle/ide/idea.gradle') + apply from: rootProject.file('gradle/compile/java.gradle') + apply from: rootProject.file('gradle/test/junit5.gradle') + apply from: rootProject.file('gradle/publishing/publication.gradle') } +apply from: rootProject.file('gradle/publishing/sonatype.gradle') diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml index 52fe33c..773fc1a 100644 --- a/config/checkstyle/checkstyle.xml +++ b/config/checkstyle/checkstyle.xml @@ -73,7 +73,6 @@ page at http://checkstyle.sourceforge.net/config.html --> - diff --git a/content-core/build.gradle b/content-core/build.gradle index 0d26d6f..62cdcc6 100644 --- a/content-core/build.gradle +++ b/content-core/build.gradle @@ -1,3 +1,3 @@ dependencies { - compile "com.fasterxml.jackson.core:jackson-core:${project.property('jackson.version')}" + api "com.fasterxml.jackson.core:jackson-core:${project.property('jackson.version')}" } diff --git a/content-core/src/main/java/module-info.java b/content-core/src/main/java/module-info.java new file mode 100644 index 0000000..c29c994 --- /dev/null +++ b/content-core/src/main/java/module-info.java @@ -0,0 +1,14 @@ +module org.xbib.content.core { + exports org.xbib.content; + exports org.xbib.content.io; + exports org.xbib.content.json; + exports org.xbib.content.settings; + exports org.xbib.content.util.geo; + exports org.xbib.content.util.unit; + requires com.fasterxml.jackson.core; + provides org.xbib.content.XContent with + org.xbib.content.json.JsonXContent; + provides org.xbib.content.settings.SettingsLoader with + org.xbib.content.settings.PropertiesSettingsLoader, + org.xbib.content.json.JsonSettingsLoader; +} diff --git a/content-core/src/test/java/org/xbib/content/XContentBuilderTest.java b/content-core/src/test/java/org/xbib/content/XContentBuilderTest.java index 7a2ed07..c8f72f0 100644 --- a/content-core/src/test/java/org/xbib/content/XContentBuilderTest.java +++ b/content-core/src/test/java/org/xbib/content/XContentBuilderTest.java @@ -1,9 +1,10 @@ package org.xbib.content; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.xbib.content.json.JsonXContent.contentBuilder; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.xbib.content.json.JsonXContent; import java.io.IOException; @@ -16,7 +17,7 @@ import java.util.Map; /** * */ -public class XContentBuilderTest extends Assert { +public class XContentBuilderTest { @Test public void testCopy() throws IOException { @@ -141,10 +142,11 @@ public class XContentBuilderTest extends Assert { assertEquals(map.toString(), "{value=4AC3B67267}"); } - @Test(expected = NullPointerException.class) - public void testNullKey() throws IOException { - XContentBuilder builder = contentBuilder(); - builder.field((String) null); + @Test + public void testNullKey() { + assertThrows(NullPointerException.class, () -> { + XContentBuilder builder = contentBuilder(); + builder.field((String) null); + }); } - } diff --git a/content-core/src/test/java/org/xbib/content/settings/SettingsTest.java b/content-core/src/test/java/org/xbib/content/settings/SettingsTest.java index c087b4c..6df296b 100644 --- a/content-core/src/test/java/org/xbib/content/settings/SettingsTest.java +++ b/content-core/src/test/java/org/xbib/content/settings/SettingsTest.java @@ -1,7 +1,9 @@ package org.xbib.content.settings; -import org.junit.Assert; -import org.junit.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import org.junit.jupiter.api.Test; import org.xbib.content.XContentHelper; import org.xbib.content.io.BytesArray; import org.xbib.content.io.BytesReference; @@ -24,7 +26,7 @@ import java.util.concurrent.TimeUnit; /** * */ -public class SettingsTest extends Assert { +public class SettingsTest { @Test public void testEmpty() { diff --git a/content-csv/src/main/java/module-info.java b/content-csv/src/main/java/module-info.java new file mode 100644 index 0000000..ffa9849 --- /dev/null +++ b/content-csv/src/main/java/module-info.java @@ -0,0 +1,3 @@ +module org.xbib.content.csv { + exports org.xbib.content.csv; +} diff --git a/content-csv/src/main/java/org/xbib/content/csv/CSVParser.java b/content-csv/src/main/java/org/xbib/content/csv/CSVParser.java index 9b1a0e7..3f0427e 100644 --- a/content-csv/src/main/java/org/xbib/content/csv/CSVParser.java +++ b/content-csv/src/main/java/org/xbib/content/csv/CSVParser.java @@ -6,16 +6,12 @@ import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.NoSuchElementException; -import java.util.logging.Level; -import java.util.logging.Logger; /** * */ public class CSVParser { - private static final Logger logger = Logger.getLogger(CSVParser.class.getName()); - private final CSVLexer lexer; private final List row; @@ -43,7 +39,7 @@ public class CSVParser { } public Iterator> iterator() { - return new Iterator>() { + return new Iterator<>() { private List current; private List getNextRow() throws IOException { @@ -56,7 +52,6 @@ public class CSVParser { try { current = getNextRow(); } catch (IOException e) { - logger.log(Level.FINE, e.getMessage(), e); throw new NoSuchElementException(e.getMessage()); } } diff --git a/content-csv/src/test/java/org/xbib/content/csv/CSVGeneratorTest.java b/content-csv/src/test/java/org/xbib/content/csv/CSVGeneratorTest.java index 6f6d639..ed0e325 100644 --- a/content-csv/src/test/java/org/xbib/content/csv/CSVGeneratorTest.java +++ b/content-csv/src/test/java/org/xbib/content/csv/CSVGeneratorTest.java @@ -1,7 +1,6 @@ package org.xbib.content.csv; -import org.junit.Test; - +import org.junit.jupiter.api.Test; import java.io.IOException; import java.io.StringWriter; import java.util.Arrays; diff --git a/content-csv/src/test/java/org/xbib/content/csv/CSVParserTest.java b/content-csv/src/test/java/org/xbib/content/csv/CSVParserTest.java index 8b47c8e..48246ee 100644 --- a/content-csv/src/test/java/org/xbib/content/csv/CSVParserTest.java +++ b/content-csv/src/test/java/org/xbib/content/csv/CSVParserTest.java @@ -1,27 +1,20 @@ package org.xbib.content.csv; -import static org.junit.Assert.assertEquals; - -import org.junit.Test; - +import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.Test; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.nio.charset.StandardCharsets; -import java.text.MessageFormat; import java.util.Iterator; import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; /** * */ public class CSVParserTest { - private static final Logger logger = Logger.getLogger(CSVParserTest.class.getName()); - @Test public void testCommaSeparated() throws IOException { InputStream in = getClass().getResourceAsStream("test.csv"); @@ -31,7 +24,6 @@ public class CSVParserTest { Iterator> it = csvParser.iterator(); while (it.hasNext()) { List row = it.next(); - //logger.log(Level.INFO, MessageFormat.format("count={0} row={1}", count, row)); count++; } } @@ -47,7 +39,6 @@ public class CSVParserTest { Iterator> it = csvParser.iterator(); while (it.hasNext()) { List row = it.next(); - //logger.log(Level.INFO, MessageFormat.format("count={0} row={1}", count, row)); count++; } } diff --git a/content-csv/src/test/java/org/xbib/content/csv/TSVParserTest.java b/content-csv/src/test/java/org/xbib/content/csv/TSVParserTest.java index 02808d9..6746178 100644 --- a/content-csv/src/test/java/org/xbib/content/csv/TSVParserTest.java +++ b/content-csv/src/test/java/org/xbib/content/csv/TSVParserTest.java @@ -1,11 +1,11 @@ package org.xbib.content.csv; -import org.junit.Test; - +import org.junit.jupiter.api.Test; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; /** * @@ -15,7 +15,7 @@ public class TSVParserTest { @Test public void testTabSeparated() throws IOException { InputStream in = getClass().getResourceAsStream("2076831-X-web.txt"); - InputStreamReader r = new InputStreamReader(in, "UTF-8"); + InputStreamReader r = new InputStreamReader(in, StandardCharsets.UTF_8); BufferedReader reader = new BufferedReader(r); // skip 3 lines reader.readLine(); @@ -24,7 +24,6 @@ public class TSVParserTest { String line; while ((line = reader.readLine()) != null) { String[] s = line.split("\\t"); - //logger.info("len={} line={}", s.length, Arrays.asList(s)); int i = 0; String sigel = i < s.length ? s[i++] : ""; String isil = i < s.length ? s[i++] : ""; @@ -40,8 +39,6 @@ public class TSVParserTest { String lastVolume = i < s.length ? s[i++] : ""; String lastIssue = i < s.length ? s[i++] : ""; String movingWall = i < s.length ? s[i] : ""; - //logger.info("lastDate={}", lastDate); } - } } diff --git a/content-csv/src/test/resources/log4j2.xml b/content-csv/src/test/resources/log4j2-test.xml similarity index 100% rename from content-csv/src/test/resources/log4j2.xml rename to content-csv/src/test/resources/log4j2-test.xml diff --git a/content-json/build.gradle b/content-json/build.gradle index 7af65c1..0b1fcf4 100644 --- a/content-json/build.gradle +++ b/content-json/build.gradle @@ -1,10 +1,9 @@ dependencies { - compile "com.fasterxml.jackson.core:jackson-databind:${project.property('jackson.version')}" - testCompile("junit:junit:${project.property('junit4.version')}") { + api "com.fasterxml.jackson.core:jackson-databind:${project.property('jackson.version')}" + testImplementation("junit:junit:${project.property('junit4.version')}") { exclude group: 'org.hamcrest' } - testCompile("org.mockito:mockito-core:${project.property('mockito.version')}") { + testImplementation("org.mockito:mockito-core:${project.property('mockito.version')}") { exclude group: 'org.hamcrest' } - testCompile "org.hamcrest:hamcrest-library:${project.property('hamcrest.version')}" } diff --git a/content-json/src/main/java/module-info.java b/content-json/src/main/java/module-info.java new file mode 100644 index 0000000..0611013 --- /dev/null +++ b/content-json/src/main/java/module-info.java @@ -0,0 +1,8 @@ +module org.xbib.content.json { + exports org.xbib.content.json.diff; + exports org.xbib.content.json.jackson; + exports org.xbib.content.json.mergepatch; + exports org.xbib.content.json.patch; + exports org.xbib.content.json.pointer; + requires com.fasterxml.jackson.databind; +} diff --git a/content-language/src/main/java/module-info.java b/content-language/src/main/java/module-info.java new file mode 100644 index 0000000..e4a3ef7 --- /dev/null +++ b/content-language/src/main/java/module-info.java @@ -0,0 +1,4 @@ +module org.xbib.content.language { + exports org.xbib.content.language; + exports org.xbib.content.language.enums; +} diff --git a/content-rdf/build.gradle b/content-rdf/build.gradle index f11f23c..1649a2b 100644 --- a/content-rdf/build.gradle +++ b/content-rdf/build.gradle @@ -1,3 +1,5 @@ dependencies { - compile project(':content-xml') + implementation project(':content-core') + implementation project(':content-resource') + implementation project(':content-xml') } diff --git a/content-rdf/src/main/java/module-info.java b/content-rdf/src/main/java/module-info.java new file mode 100644 index 0000000..73edb1b --- /dev/null +++ b/content-rdf/src/main/java/module-info.java @@ -0,0 +1,17 @@ +module org.xbib.content.rdf { + exports org.xbib.content.rdf; + exports org.xbib.content.rdf.internal; + exports org.xbib.content.rdf.io.json; + exports org.xbib.content.rdf.io.nquads; + exports org.xbib.content.rdf.io.ntriple; + exports org.xbib.content.rdf.io.rdfxml; + exports org.xbib.content.rdf.io.sink; + exports org.xbib.content.rdf.io.source; + exports org.xbib.content.rdf.io.turtle; + exports org.xbib.content.rdf.io.xml; + exports org.xbib.content.rdf.util; + requires org.xbib.content.core; + requires org.xbib.content.resource; + requires org.xbib.content.xml; + requires java.xml; +} diff --git a/content-rdf/src/main/java/org/xbib/content/rdf/internal/DefaultRdfGraph.java b/content-rdf/src/main/java/org/xbib/content/rdf/internal/DefaultRdfGraph.java index 9aff712..a4e64fd 100644 --- a/content-rdf/src/main/java/org/xbib/content/rdf/internal/DefaultRdfGraph.java +++ b/content-rdf/src/main/java/org/xbib/content/rdf/internal/DefaultRdfGraph.java @@ -13,19 +13,15 @@ import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; -import java.util.logging.Level; -import java.util.logging.Logger; /** * */ public class DefaultRdfGraph implements RdfGraph { - private static final Logger logger = Logger.getLogger(DefaultRdfGraph.class.getName()); - private RdfGraphParams params = DefaultRdfGraphParams.DEFAULT_PARAMS; - private Map resources = new LinkedHashMap<>(); + private final Map resources = new LinkedHashMap<>(); @Override public Iterator getResources() { @@ -151,8 +147,6 @@ public class DefaultRdfGraph implements RdfGraph { if (r != null) { list.add(new DefaultTriple(resource1, pred, r.id())); list.addAll(unfold(r)); - } else { - logger.log(Level.SEVERE, "huh? {}", resource1.id()); } } else { list.addAll(unfold(resource1)); diff --git a/content-rdf/src/main/java/org/xbib/content/rdf/internal/DefaultResource.java b/content-rdf/src/main/java/org/xbib/content/rdf/internal/DefaultResource.java index 708884a..ee5210a 100644 --- a/content-rdf/src/main/java/org/xbib/content/rdf/internal/DefaultResource.java +++ b/content-rdf/src/main/java/org/xbib/content/rdf/internal/DefaultResource.java @@ -18,7 +18,6 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; -import java.util.logging.Logger; import java.util.stream.Collectors; /** @@ -27,8 +26,9 @@ import java.util.stream.Collectors; public class DefaultResource implements Resource, Comparable, XSDResourceIdentifiers { static final String GENID = "genid"; + static final String PLACEHOLDER = "_:"; - private static final Logger logger = Logger.getLogger(DefaultResource.class.getName()); + private static final String UNDERSCORE = "_"; private final MultiMap attributes; @@ -164,7 +164,6 @@ public class DefaultResource implements Resource, Comparable, XSDResou return child.add(triple); } else { // nothing found, continue with a new resource with new subject - logger.info("nothing found!!! my ID is " + id()); return new DefaultResource(otherId).add(triple); } } diff --git a/content-rdf/src/main/java/org/xbib/content/rdf/io/json/JsonContentGenerator.java b/content-rdf/src/main/java/org/xbib/content/rdf/io/json/JsonContentGenerator.java index acd3062..5b8e840 100644 --- a/content-rdf/src/main/java/org/xbib/content/rdf/io/json/JsonContentGenerator.java +++ b/content-rdf/src/main/java/org/xbib/content/rdf/io/json/JsonContentGenerator.java @@ -15,15 +15,12 @@ import java.io.OutputStreamWriter; import java.io.Writer; import java.nio.charset.StandardCharsets; import java.util.Map; -import java.util.logging.Level; -import java.util.logging.Logger; /** * */ public class JsonContentGenerator implements RdfContentGenerator, Flushable { - private static final Logger logger = Logger.getLogger(JsonContentGenerator.class.getName()); private final Writer writer; private boolean nsWritten; @@ -54,16 +51,12 @@ public class JsonContentGenerator implements RdfContentGenerator, Flushable { - private static final Logger logger = Logger.getLogger(NTripleContentGenerator.class.getName()); - private static final char LF = '\n'; private final Writer writer; @@ -95,13 +91,9 @@ public class NTripleContentGenerator @Override public NTripleContentGenerator receive(Resource resource) throws IOException { - resource.triples().forEach(t -> { - try { - writer.write(writeStatement(t)); - } catch (IOException e) { - logger.log(Level.FINE, e.getMessage(), e); - } - }); + for (Triple t : resource.triples()) { + writer.write(writeStatement(t)); + } return this; } diff --git a/content-rdf/src/main/java/org/xbib/content/rdf/io/ntriple/NTriplesParser.java b/content-rdf/src/main/java/org/xbib/content/rdf/io/ntriple/NTriplesParser.java index 03baf55..1ef35f0 100644 --- a/content-rdf/src/main/java/org/xbib/content/rdf/io/ntriple/NTriplesParser.java +++ b/content-rdf/src/main/java/org/xbib/content/rdf/io/ntriple/NTriplesParser.java @@ -5,16 +5,12 @@ import org.xbib.content.rdf.io.sink.TripleSink; import java.io.IOException; import java.util.BitSet; -import java.util.logging.Level; -import java.util.logging.Logger; /** * Implementation of streaming NTriples parser. */ public final class NTriplesParser implements CharSink { - private static final Logger logger = Logger.getLogger(NTriplesParser.class.getName()); - private static final short PARSING_OUTSIDE = 0; private static final short PARSING_URI = 1; private static final short PARSING_BNODE = 2; @@ -118,7 +114,7 @@ public final class NTriplesParser implements CharSink { parsingState = PARSING_OUTSIDE; processOutsideChar(buffer, pos); } else { - logger.log(Level.SEVERE, "unexpected character '" + buffer[pos] + "' after literal"); + throw new IOException("unexpected character '" + buffer[pos] + "' after literal"); } } else if (parsingState == PARSING_LITERAL_TYPE) { processLiteralTypeChar(buffer, pos); @@ -159,7 +155,7 @@ public final class NTriplesParser implements CharSink { } else if (type.startsWith("^^<") && type.charAt(type.length() - 2) == '>') { onTypedLiteral(literalObj, type.substring(3, type.length() - 2 - trimSize)); } else { - logger.log(Level.SEVERE, "literal type '" + type + "' can not be parsed"); + throw new IOException("literal type '" + type + "' can not be parsed"); } parsingState = PARSING_OUTSIDE; if (trimSize > 0) { @@ -190,7 +186,7 @@ public final class NTriplesParser implements CharSink { break; default: if (!WHITESPACE.get(buffer[pos])) { - logger.log(Level.SEVERE, "unexpected character '" + buffer[pos] + "'"); + throw new IOException("unexpected character '" + buffer[pos] + "'"); } } } @@ -199,13 +195,13 @@ public final class NTriplesParser implements CharSink { if (waitingForSentenceEnd) { waitingForSentenceEnd = false; } else { - logger.log(Level.SEVERE, "unexpected end of sentence"); + throw new IOException("unexpected end of sentence"); } } private void onNonLiteral(String uri) throws IOException { if (waitingForSentenceEnd) { - logger.log(Level.SEVERE, "endStream of sentence expected"); + throw new IOException("endStream of sentence expected"); } if (subj == null) { subj = uri; @@ -220,9 +216,9 @@ public final class NTriplesParser implements CharSink { private void onPlainLiteral(String value, String lang) throws IOException { if (subj == null || pred == null) { if (waitingForSentenceEnd) { - logger.log(Level.SEVERE, "end of sentence expected"); + throw new IOException("end of sentence expected"); } else { - logger.log(Level.SEVERE, "literal is not an object"); + throw new IOException("literal is not an object"); } } sink.addPlainLiteral(subj, pred, value, lang); @@ -232,9 +228,9 @@ public final class NTriplesParser implements CharSink { private void onTypedLiteral(String value, String type) throws IOException { if (subj == null || pred == null) { if (waitingForSentenceEnd) { - logger.log(Level.SEVERE, "end of sentence expected"); + throw new IOException("end of sentence expected"); } else { - logger.log(Level.SEVERE, "literal is not an object"); + throw new IOException("literal is not an object"); } } sink.addTypedLiteral(subj, pred, value, type); @@ -281,7 +277,7 @@ public final class NTriplesParser implements CharSink { @Override public void endStream() throws IOException { if (tokenStartPos != -1 || waitingForSentenceEnd) { - logger.log(Level.SEVERE, "unexpected end of stream"); + throw new IOException("unexpected end of stream"); } sink.endStream(); } @@ -331,7 +327,7 @@ public final class NTriplesParser implements CharSink { case 'U': int sequenceLength = ch == 'u' ? 4 : 8; if (i + sequenceLength >= limit) { - logger.log(Level.SEVERE, "error parsing escape sequence '\\" + ch + "'"); + throw new IOException("error parsing escape sequence '\\" + ch + "'"); } String code = str.substring(i + 1, i + 1 + sequenceLength); i += sequenceLength; @@ -340,7 +336,7 @@ public final class NTriplesParser implements CharSink { int value = Integer.parseInt(code, 16); result.append((char) value); } catch (NumberFormatException nfe) { - logger.log(Level.SEVERE, "error parsing escape sequence '\\" + ch + "'"); + throw new IOException("error parsing escape sequence '\\" + ch + "'"); } break; default: diff --git a/content-rdf/src/main/java/org/xbib/content/rdf/io/ntriple/NTriplesSerializer.java b/content-rdf/src/main/java/org/xbib/content/rdf/io/ntriple/NTriplesSerializer.java index 8aeb242..b819bf8 100644 --- a/content-rdf/src/main/java/org/xbib/content/rdf/io/ntriple/NTriplesSerializer.java +++ b/content-rdf/src/main/java/org/xbib/content/rdf/io/ntriple/NTriplesSerializer.java @@ -6,8 +6,6 @@ import org.xbib.content.rdf.io.sink.TripleSink; import java.io.IOException; import java.util.BitSet; -import java.util.logging.Level; -import java.util.logging.Logger; /** * Implementation of {@link org.xbib.content.rdf.io.sink.TripleSink} which serializes triples to @@ -17,7 +15,6 @@ public class NTriplesSerializer implements TripleSink, RDF { protected static final String DOT_EOL = ".\n"; protected static final char SPACE = ' '; - private static final Logger logger = Logger.getLogger(NTriplesSerializer.class.getName()); private static final char QUOTE = '"'; private static final char URI_START = '<'; private static final char URI_END = '>'; @@ -118,7 +115,7 @@ public class NTriplesSerializer implements TripleSink, RDF { return str; } StringBuilder result = new StringBuilder(limit); - result.append(str.substring(0, pos)); + result.append(str, 0, pos); for (; pos < limit; pos++) { char ch = str.charAt(pos); if (ch < 0x80) { @@ -151,41 +148,29 @@ public class NTriplesSerializer implements TripleSink, RDF { } @Override - public void addNonLiteral(String subj, String pred, String obj) { - try { - startTriple(subj, pred); - serializeBnodeOrUri(obj); - sink.process(DOT_EOL); - } catch (IOException e) { - logger.log(Level.FINE, e.getMessage(), e); - } + public void addNonLiteral(String subj, String pred, String obj) throws IOException { + startTriple(subj, pred); + serializeBnodeOrUri(obj); + sink.process(DOT_EOL); } @Override - public void addPlainLiteral(String subj, String pred, String content, String lang) { - try { - startTriple(subj, pred); - addContent(content); - if (lang != null) { - sink.process('@').process(lang); - } - sink.process(SPACE).process(DOT_EOL); - } catch (IOException e) { - logger.log(Level.FINE, e.getMessage(), e); + public void addPlainLiteral(String subj, String pred, String content, String lang) throws IOException { + startTriple(subj, pred); + addContent(content); + if (lang != null) { + sink.process('@').process(lang); } + sink.process(SPACE).process(DOT_EOL); } @Override - public void addTypedLiteral(String subj, String pred, String content, String type) { - try { - startTriple(subj, pred); - addContent(content); - sink.process("^^"); - serializeUri(type); - sink.process(DOT_EOL); - } catch (IOException e) { - logger.log(Level.FINE, e.getMessage(), e); - } + public void addTypedLiteral(String subj, String pred, String content, String type) throws IOException { + startTriple(subj, pred); + addContent(content); + sink.process("^^"); + serializeUri(type); + sink.process(DOT_EOL); } @Override diff --git a/content-rdf/src/main/java/org/xbib/content/rdf/io/rdfxml/RdfXmlContentGenerator.java b/content-rdf/src/main/java/org/xbib/content/rdf/io/rdfxml/RdfXmlContentGenerator.java index 60d3db2..55f15e8 100644 --- a/content-rdf/src/main/java/org/xbib/content/rdf/io/rdfxml/RdfXmlContentGenerator.java +++ b/content-rdf/src/main/java/org/xbib/content/rdf/io/rdfxml/RdfXmlContentGenerator.java @@ -18,16 +18,12 @@ import java.io.OutputStreamWriter; import java.io.Writer; import java.nio.charset.StandardCharsets; import java.util.Map; -import java.util.logging.Level; -import java.util.logging.Logger; /** * RDF/XML writer. */ public class RdfXmlContentGenerator implements RdfContentGenerator, Flushable, RdfConstants { - private static final Logger logger = Logger.getLogger(RdfXmlContentGenerator.class.getName()); - private final Writer writer; private boolean writingStarted; @@ -119,7 +115,9 @@ public class RdfXmlContentGenerator implements RdfContentGenerator"); - writeNewLine(); - lastWrittenSubject = subj; - } - writer.write("\t"); - writeStartOfStartTag(predNamespace, predLocalName); - if (obj instanceof Resource) { - Resource objRes = (Resource) obj; - if (objRes.isEmbedded()) { - writeAttribute(NS_URI, "nodeID", objRes.id().toString()); - } else { - writeAttribute(NS_URI, "resource", objRes.id().toString()); - } - writer.write("/>"); - } else if (obj instanceof Literal) { - Literal l = (Literal) obj; - if (l.lang() != null) { - writeAttribute("xml:lang", l.lang()); - } - boolean isXMLLiteral = false; - IRI datatype = l.type(); - if (datatype != null) { - isXMLLiteral = datatype.equals(RDF_XMLLITERAL); - if (isXMLLiteral) { - writeAttribute(NS_URI, "parseType", "Literal"); - } else { - writeAttribute(NS_URI, "datatype", datatype.toString()); - } - } - writer.write(">"); - if (isXMLLiteral) { - writer.write(obj.toString()); - } else { - writer.write(escapeCharacterData(obj.toString())); - } - writeEndTag(predNamespace, predLocalName); - } - writeNewLine(); - } catch (IOException e) { - logger.log(Level.FINE, e.getMessage(), e); + private RdfXmlContentGenerator writeTriple(Triple triple) throws IOException { + if (!writingStarted) { + throw new IOException("document writing has not yet been started"); } + Resource subj = triple.subject(); + IRI pred = triple.predicate(); + Node obj = triple.object(); + String predString = pred.toString(); + int predSplitIdx = findURISplitIndex(predString); + if (predSplitIdx == -1) { + throw new IOException("unable to create XML namespace-qualified name for predicate: " + predString); + } + String predNamespace = predString.substring(0, predSplitIdx); + String predLocalName = predString.substring(predSplitIdx); + if (!headerWritten) { + writeHeader(); + } + if (!subj.equals(lastWrittenSubject)) { + flushPendingStatements(); + writeNewLine(); + writeStartOfStartTag(NS_URI, "Description"); + if (subj.isEmbedded()) { + writeAttribute(NS_URI, "nodeID", subj.toString()); + } else { + writeAttribute(NS_URI, "about", subj.toString()); + } + writer.write(">"); + writeNewLine(); + lastWrittenSubject = subj; + } + writer.write("\t"); + writeStartOfStartTag(predNamespace, predLocalName); + if (obj instanceof Resource) { + Resource objRes = (Resource) obj; + if (objRes.isEmbedded()) { + writeAttribute(NS_URI, "nodeID", objRes.id().toString()); + } else { + writeAttribute(NS_URI, "resource", objRes.id().toString()); + } + writer.write("/>"); + } else if (obj instanceof Literal) { + Literal l = (Literal) obj; + if (l.lang() != null) { + writeAttribute("xml:lang", l.lang()); + } + boolean isXMLLiteral = false; + IRI datatype = l.type(); + if (datatype != null) { + isXMLLiteral = datatype.equals(RDF_XMLLITERAL); + if (isXMLLiteral) { + writeAttribute(NS_URI, "parseType", "Literal"); + } else { + writeAttribute(NS_URI, "datatype", datatype.toString()); + } + } + writer.write(">"); + if (isXMLLiteral) { + writer.write(obj.toString()); + } else { + writer.write(escapeCharacterData(obj.toString())); + } + writeEndTag(predNamespace, predLocalName); + } + writeNewLine(); return this; } diff --git a/content-rdf/src/main/java/org/xbib/content/rdf/io/rdfxml/RdfXmlContentParser.java b/content-rdf/src/main/java/org/xbib/content/rdf/io/rdfxml/RdfXmlContentParser.java index 41e56ef..c0ed15b 100644 --- a/content-rdf/src/main/java/org/xbib/content/rdf/io/rdfxml/RdfXmlContentParser.java +++ b/content-rdf/src/main/java/org/xbib/content/rdf/io/rdfxml/RdfXmlContentParser.java @@ -16,8 +16,8 @@ import org.xbib.content.rdf.internal.DefaultLiteral; import org.xbib.content.rdf.internal.DefaultTriple; import org.xbib.content.rdf.io.xml.XmlHandler; import org.xbib.content.resource.IRI; -import org.xbib.content.resource.IRINamespaceContext; import org.xbib.content.resource.IRISyntaxException; +import org.xbib.content.resource.NamespaceContext; import org.xbib.content.resource.Node; import org.xbib.content.xml.util.XMLUtil; import org.xml.sax.Attributes; @@ -38,8 +38,6 @@ import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; -import java.util.logging.Level; -import java.util.logging.Logger; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; @@ -56,8 +54,6 @@ import javax.xml.parsers.SAXParserFactory; */ public class RdfXmlContentParser implements RdfConstants, RdfContentParser { - private static final Logger logger = Logger.getLogger(RdfXmlContentParser.class.getName()); - private final Reader reader; private final Resource resource = new DefaultAnonymousResource(); @@ -245,7 +241,6 @@ public class RdfXmlContentParser implements RdfConst try { uri = IRI.create(uriString); } catch (IRISyntaxException e) { - logger.log(Level.FINE, e.getMessage(), e); // illegal URI, try repair uri = IRI.create(uriString .replace(" ", "%20") @@ -418,18 +413,18 @@ public class RdfXmlContentParser implements RdfConst private StringBuilder xmlLiteral = null; - private IRINamespaceContext namespaceContext; + private NamespaceContext namespaceContext; private int literalLevel = 0; // level in XMLLiteral @Override - public XmlHandler setNamespaceContext(IRINamespaceContext namespaceContext) { + public XmlHandler setNamespaceContext(NamespaceContext namespaceContext) { this.namespaceContext = namespaceContext; return this; } @Override - public IRINamespaceContext getNamespaceContext() { + public NamespaceContext getNamespaceContext() { return namespaceContext; } diff --git a/content-rdf/src/main/java/org/xbib/content/rdf/io/sink/QuadSink.java b/content-rdf/src/main/java/org/xbib/content/rdf/io/sink/QuadSink.java index f80b0cd..8396b07 100644 --- a/content-rdf/src/main/java/org/xbib/content/rdf/io/sink/QuadSink.java +++ b/content-rdf/src/main/java/org/xbib/content/rdf/io/sink/QuadSink.java @@ -1,5 +1,7 @@ package org.xbib.content.rdf.io.sink; +import java.io.IOException; + /** * Interface for quad consuming. */ @@ -12,8 +14,9 @@ public interface QuadSink extends TripleSink { * @param pred predicate's IRI * @param obj object's IRI or BNode name * @param graph graph's IRI + * @throws IOException if handling of triple fails */ - void addNonLiteral(String subj, String pred, String obj, String graph); + void addNonLiteral(String subj, String pred, String obj, String graph) throws IOException; /** * Callback for handling triples with plain literal objects. @@ -23,8 +26,9 @@ public interface QuadSink extends TripleSink { * @param content unescaped string representation of content * @param lang content's lang, can be null if no language specified * @param graph graph's IRI + * @throws IOException if handling of triple fails */ - void addPlainLiteral(String subj, String pred, String content, String lang, String graph); + void addPlainLiteral(String subj, String pred, String content, String lang, String graph) throws IOException; /** * Callback for handling triples with typed literal objects. @@ -34,7 +38,8 @@ public interface QuadSink extends TripleSink { * @param content unescaped string representation of content * @param type literal datatype's IRI * @param graph graph's IRI + * @throws IOException if handling of triple fails */ - void addTypedLiteral(String subj, String pred, String content, String type, String graph); + void addTypedLiteral(String subj, String pred, String content, String type, String graph) throws IOException; } diff --git a/content-rdf/src/main/java/org/xbib/content/rdf/io/sink/RdfContentBuilderSink.java b/content-rdf/src/main/java/org/xbib/content/rdf/io/sink/RdfContentBuilderSink.java index bff46c9..dae5b88 100644 --- a/content-rdf/src/main/java/org/xbib/content/rdf/io/sink/RdfContentBuilderSink.java +++ b/content-rdf/src/main/java/org/xbib/content/rdf/io/sink/RdfContentBuilderSink.java @@ -13,16 +13,13 @@ import org.xbib.content.rdf.internal.DefaultTriple; import org.xbib.content.resource.IRI; import java.io.IOException; -import java.util.logging.Level; -import java.util.logging.Logger; +import java.util.Iterator; /** * */ public class RdfContentBuilderSink implements QuadSink { - private static final Logger logger = Logger.getLogger(RdfContentBuilderSink.class.getName()); - private final RdfGraph graph; private final RdfContentBuilderProvider provider; @@ -34,81 +31,57 @@ public class RdfContentBuilderSink implements QuadSink { } @Override - public void addNonLiteral(String subj, String pred, String obj) { - try { - Resource s = DefaultResource.create(graph.getParams().getNamespaceContext(), subj); - IRI p = IRI.create(pred); - Resource o = DefaultResource.create(graph.getParams().getNamespaceContext(), obj); - Triple t = new DefaultTriple(s, p, o); - graph.receive(t); - } catch (IOException e) { - logger.log(Level.SEVERE, e.getMessage(), e); - } + public void addNonLiteral(String subj, String pred, String obj) throws IOException { + Resource s = DefaultResource.create(graph.getParams().getNamespaceContext(), subj); + IRI p = IRI.create(pred); + Resource o = DefaultResource.create(graph.getParams().getNamespaceContext(), obj); + Triple t = new DefaultTriple(s, p, o); + graph.receive(t); } @Override - public void addNonLiteral(String subj, String pred, String obj, String graphIRI) { - try { - Resource s = DefaultResource.create(graph.getParams().getNamespaceContext(), subj); - IRI p = IRI.create(pred); - Resource o = DefaultResource.create(graph.getParams().getNamespaceContext(), obj); - Triple t = new DefaultTriple(s, p, o); - graph.receive(t); - } catch (IOException e) { - logger.log(Level.SEVERE, e.getMessage(), e); - } + public void addNonLiteral(String subj, String pred, String obj, String graphIRI) throws IOException { + Resource s = DefaultResource.create(graph.getParams().getNamespaceContext(), subj); + IRI p = IRI.create(pred); + Resource o = DefaultResource.create(graph.getParams().getNamespaceContext(), obj); + Triple t = new DefaultTriple(s, p, o); + graph.receive(t); } @Override - public void addPlainLiteral(String subj, String pred, String content, String lang) { - try { - Resource s = DefaultResource.create(graph.getParams().getNamespaceContext(), subj); - IRI p = IRI.create(pred); - Literal o = new DefaultLiteral(content).lang(lang); - Triple t = new DefaultTriple(s, p, o); - graph.receive(t); - } catch (IOException e) { - logger.log(Level.SEVERE, e.getMessage(), e); - } + public void addPlainLiteral(String subj, String pred, String content, String lang) throws IOException { + Resource s = DefaultResource.create(graph.getParams().getNamespaceContext(), subj); + IRI p = IRI.create(pred); + Literal o = new DefaultLiteral(content).lang(lang); + Triple t = new DefaultTriple(s, p, o); + graph.receive(t); } @Override - public void addPlainLiteral(String subj, String pred, String content, String lang, String graphIRI) { - try { - Resource s = DefaultResource.create(graph.getParams().getNamespaceContext(), subj); - IRI p = IRI.create(pred); - Literal o = new DefaultLiteral(content).lang(lang); - Triple t = new DefaultTriple(s, p, o); - graph.receive(t); - } catch (IOException e) { - logger.log(Level.SEVERE, e.getMessage(), e); - } + public void addPlainLiteral(String subj, String pred, String content, String lang, String graphIRI) throws IOException { + Resource s = DefaultResource.create(graph.getParams().getNamespaceContext(), subj); + IRI p = IRI.create(pred); + Literal o = new DefaultLiteral(content).lang(lang); + Triple t = new DefaultTriple(s, p, o); + graph.receive(t); } @Override - public void addTypedLiteral(String subj, String pred, String content, String type) { - try { - Resource s = DefaultResource.create(graph.getParams().getNamespaceContext(), subj); - IRI p = IRI.create(pred); - Literal o = new DefaultLiteral(content).type(IRI.create(type)); - Triple t = new DefaultTriple(s, p, o); - graph.receive(t); - } catch (IOException e) { - logger.log(Level.SEVERE, e.getMessage(), e); - } + public void addTypedLiteral(String subj, String pred, String content, String type) throws IOException { + Resource s = DefaultResource.create(graph.getParams().getNamespaceContext(), subj); + IRI p = IRI.create(pred); + Literal o = new DefaultLiteral(content).type(IRI.create(type)); + Triple t = new DefaultTriple(s, p, o); + graph.receive(t); } @Override - public void addTypedLiteral(String subj, String pred, String content, String type, String graphIRI) { - try { - Resource s = DefaultResource.create(graph.getParams().getNamespaceContext(), subj); - IRI p = IRI.create(pred); - Literal o = new DefaultLiteral(content).type(IRI.create(type)); - Triple t = new DefaultTriple(s, p, o); - graph.receive(t); - } catch (IOException e) { - logger.log(Level.SEVERE, e.getMessage(), e); - } + public void addTypedLiteral(String subj, String pred, String content, String type, String graphIRI) throws IOException { + Resource s = DefaultResource.create(graph.getParams().getNamespaceContext(), subj); + IRI p = IRI.create(pred); + Literal o = new DefaultLiteral(content).type(IRI.create(type)); + Triple t = new DefaultTriple(s, p, o); + graph.receive(t); } @Override @@ -125,22 +98,16 @@ public class RdfContentBuilderSink implements QuadSink { public void endStream() throws IOException { if (graph.getResources() != null) { if (provider != null) { - graph.getResources().forEachRemaining(resource -> { + Iterator iterator = graph.getResources(); + while (iterator.hasNext()) { + Resource resource = iterator.next(); RdfContentBuilder rdfContentBuilder; - try { rdfContentBuilder = provider.newContentBuilder(); rdfContentBuilder.startStream(); rdfContentBuilder.receive(resource); rdfContentBuilder.endStream(); - } catch (IOException e) { - logger.log(Level.SEVERE, e.getMessage(), e); - } - }); - } else { - logger.log(Level.WARNING, "no RDF content builder provider"); + } } - } else { - logger.log(Level.WARNING, "no graph resources"); } } diff --git a/content-rdf/src/main/java/org/xbib/content/rdf/io/sink/TripleSink.java b/content-rdf/src/main/java/org/xbib/content/rdf/io/sink/TripleSink.java index b9b0869..b71fd8b 100644 --- a/content-rdf/src/main/java/org/xbib/content/rdf/io/sink/TripleSink.java +++ b/content-rdf/src/main/java/org/xbib/content/rdf/io/sink/TripleSink.java @@ -1,5 +1,7 @@ package org.xbib.content.rdf.io.sink; +import java.io.IOException; + /** * Interface for triple consuming. */ @@ -11,8 +13,9 @@ public interface TripleSink extends Sink { * @param subj subject's IRI or BNode name * @param pred predicate's IRI * @param obj object's IRI or BNode name + * @throws IOException if handling of triple fails */ - void addNonLiteral(String subj, String pred, String obj); + void addNonLiteral(String subj, String pred, String obj) throws IOException; /** * Callback for handling triples with plain literal objects. @@ -21,8 +24,9 @@ public interface TripleSink extends Sink { * @param pred predicate's IRI * @param content unescaped string representation of content * @param lang content's lang, can be null if no language specified + * @throws IOException if handling of triple fails */ - void addPlainLiteral(String subj, String pred, String content, String lang); + void addPlainLiteral(String subj, String pred, String content, String lang) throws IOException; /** * Callback for handling triples with typed literal objects. @@ -31,7 +35,7 @@ public interface TripleSink extends Sink { * @param pred predicate's IRI * @param content unescaped string representation of content * @param type literal datatype's IRI + * @throws IOException if handling of triple fails */ - void addTypedLiteral(String subj, String pred, String content, String type); - + void addTypedLiteral(String subj, String pred, String content, String type) throws IOException; } diff --git a/content-rdf/src/main/java/org/xbib/content/rdf/io/turtle/TurtleContentGenerator.java b/content-rdf/src/main/java/org/xbib/content/rdf/io/turtle/TurtleContentGenerator.java index 5ab1bff..bfa7ba2 100644 --- a/content-rdf/src/main/java/org/xbib/content/rdf/io/turtle/TurtleContentGenerator.java +++ b/content-rdf/src/main/java/org/xbib/content/rdf/io/turtle/TurtleContentGenerator.java @@ -19,16 +19,12 @@ import java.io.Writer; import java.nio.charset.StandardCharsets; import java.util.LinkedList; import java.util.Map; -import java.util.logging.Level; -import java.util.logging.Logger; /** * */ public class TurtleContentGenerator implements RdfContentGenerator, Flushable { - private static final Logger logger = Logger.getLogger(TurtleContentGenerator.class.getName()); - private static final char LF = '\n'; private static final char TAB = '\t'; private static final String TYPE = RdfConstants.NS_URI + "type"; @@ -43,15 +39,15 @@ public class TurtleContentGenerator implements RdfContentGenerator embedded; + private final LinkedList embedded; - private LinkedList triples; + private final LinkedList triples; private Triple triple; private boolean nsWritten; - private StringBuilder sb; + private final StringBuilder sb; private Resource resource; @@ -117,13 +113,9 @@ public class TurtleContentGenerator implements RdfContentGenerator receive(Resource resource) throws IOException { - resource.triples().forEach(t -> { - try { + for (Triple t : resource.triples()) { writeTriple(t); - } catch (IOException e) { - logger.log(Level.FINE, e.getMessage(), e); - } - }); + } while (!embedded.isEmpty()) { closeEmbeddedResource(); } diff --git a/content-rdf/src/main/java/org/xbib/content/rdf/io/turtle/TurtleContentParser.java b/content-rdf/src/main/java/org/xbib/content/rdf/io/turtle/TurtleContentParser.java index 61d11d9..aa42d88 100644 --- a/content-rdf/src/main/java/org/xbib/content/rdf/io/turtle/TurtleContentParser.java +++ b/content-rdf/src/main/java/org/xbib/content/rdf/io/turtle/TurtleContentParser.java @@ -16,8 +16,9 @@ import org.xbib.content.rdf.internal.DefaultLiteral; import org.xbib.content.rdf.internal.DefaultResource; import org.xbib.content.rdf.internal.DefaultTriple; import org.xbib.content.resource.IRI; +import org.xbib.content.resource.NamespaceContext; import org.xbib.content.resource.Node; -import org.xbib.content.resource.XmlNamespaceContext; +import org.xbib.content.xml.XmlNamespaceContext; import java.io.EOFException; import java.io.IOException; @@ -29,8 +30,6 @@ import java.io.UnsupportedEncodingException; import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.LinkedList; -import java.util.logging.Level; -import java.util.logging.Logger; /** * Turtle - Terse RDF Triple Parser. @@ -41,8 +40,6 @@ import java.util.logging.Logger; */ public class TurtleContentParser implements RdfContentParser { - private static final Logger logger = Logger.getLogger(TurtleContentParser.class.getName()); - private final Resource resource = new DefaultAnonymousResource(); private final HashMap bnodes = new HashMap<>(); @@ -93,7 +90,7 @@ public class TurtleContentParser implements RdfConte /** * The namespace context. */ - private XmlNamespaceContext context = XmlNamespaceContext.newDefaultInstance(); + private NamespaceContext context; public TurtleContentParser(InputStream in) throws IOException { this(new InputStreamReader(in, StandardCharsets.UTF_8)); @@ -101,6 +98,7 @@ public class TurtleContentParser implements RdfConte public TurtleContentParser(Reader reader) { this.reader = new PushbackReader(reader, 2); + this.context = XmlNamespaceContext.newInstance(); } public static String decode(String s, String encoding) throws UnsupportedEncodingException { @@ -154,7 +152,7 @@ public class TurtleContentParser implements RdfConte return this; } - public TurtleContentParser context(XmlNamespaceContext context) { + public TurtleContentParser context(NamespaceContext context) { this.context = context; return this; } @@ -781,7 +779,7 @@ public class TurtleContentParser implements RdfConte if ((char) ch != v) { String message = (subject != null ? subject : "") + " unexpected character: '" + (char) ch + "' expected: '" + v + "'"; - logger.log(Level.WARNING, message); + throw new IOException(message); } } diff --git a/content-rdf/src/main/java/org/xbib/content/rdf/io/turtle/TurtleSerializer.java b/content-rdf/src/main/java/org/xbib/content/rdf/io/turtle/TurtleSerializer.java index bb20939..13b9205 100644 --- a/content-rdf/src/main/java/org/xbib/content/rdf/io/turtle/TurtleSerializer.java +++ b/content-rdf/src/main/java/org/xbib/content/rdf/io/turtle/TurtleSerializer.java @@ -8,8 +8,6 @@ import java.io.IOException; import java.util.HashSet; import java.util.LinkedList; import java.util.Set; -import java.util.logging.Level; -import java.util.logging.Logger; /** * Implementation of {@link org.xbib.content.rdf.io.sink.TripleSink} which serializes triples to {@link @@ -18,8 +16,6 @@ import java.util.logging.Logger; */ public final class TurtleSerializer implements TripleSink, RDF { - private static final Logger logger = Logger.getLogger(TurtleSerializer.class.getName()); - private static final String DOT_EOL = " .\n"; private static final String COMMA_EOL = " ,\n"; private static final String SEMICOLON_EOL = " ;\n"; @@ -58,47 +54,35 @@ public final class TurtleSerializer implements TripleSink, RDF { } @Override - public void addNonLiteral(String subj, String pred, String obj) { - try { - startTriple(subj, pred); - if (obj.startsWith(BNODE_PREFIX)) { - if (!namedBnodes.contains(obj) && obj.endsWith(SHORTENABLE_BNODE_SUFFIX)) { - openBnode(obj); - } else { - sink.process(obj); - } + public void addNonLiteral(String subj, String pred, String obj) throws IOException { + startTriple(subj, pred); + if (obj.startsWith(BNODE_PREFIX)) { + if (!namedBnodes.contains(obj) && obj.endsWith(SHORTENABLE_BNODE_SUFFIX)) { + openBnode(obj); } else { - serializeUri(obj); + sink.process(obj); } - } catch (IOException e) { - logger.log(Level.FINE, e.getMessage(), e); + } else { + serializeUri(obj); } } @Override - public void addPlainLiteral(String subj, String pred, String content, String lang) { - try { - startTriple(subj, pred); - addContent(content); - if (lang != null) { - sink.process('@').process(lang); - } - } catch (IOException e) { - logger.log(Level.FINE, e.getMessage(), e); + public void addPlainLiteral(String subj, String pred, String content, String lang) throws IOException { + startTriple(subj, pred); + addContent(content); + if (lang != null) { + sink.process('@').process(lang); } } @Override - public void addTypedLiteral(String subj, String pred, String content, String type) { - try { - startTriple(subj, pred); - addContent(content); - sink.process("^^"); - serializeUri(type); - } catch (IOException e) { - logger.log(Level.FINE, e.getMessage(), e); - } - } + public void addTypedLiteral(String subj, String pred, String content, String type) throws IOException { + startTriple(subj, pred); + addContent(content); + sink.process("^^"); + serializeUri(type); +} @Override public void startStream() throws IOException { diff --git a/content-rdf/src/main/java/org/xbib/content/rdf/io/xml/XmlHandler.java b/content-rdf/src/main/java/org/xbib/content/rdf/io/xml/XmlHandler.java index bfe3cf5..18ff041 100644 --- a/content-rdf/src/main/java/org/xbib/content/rdf/io/xml/XmlHandler.java +++ b/content-rdf/src/main/java/org/xbib/content/rdf/io/xml/XmlHandler.java @@ -2,7 +2,7 @@ package org.xbib.content.rdf.io.xml; import org.xbib.content.rdf.RdfContentBuilder; import org.xbib.content.rdf.RdfContentParams; -import org.xbib.content.resource.IRINamespaceContext; +import org.xbib.content.resource.NamespaceContext; import org.xml.sax.ContentHandler; import org.xml.sax.DTDHandler; import org.xml.sax.EntityResolver; @@ -15,9 +15,9 @@ import org.xml.sax.ErrorHandler; public interface XmlHandler

extends EntityResolver, DTDHandler, ContentHandler, ErrorHandler { - IRINamespaceContext getNamespaceContext(); + NamespaceContext getNamespaceContext(); - XmlHandler

setNamespaceContext(IRINamespaceContext namespaceContext); + XmlHandler

setNamespaceContext(NamespaceContext namespaceContext); XmlHandler

setDefaultNamespace(String prefix, String uri); diff --git a/content-rdf/src/test/java/org/xbib/content/rdf/IRINamespaceCompactionTest.java b/content-rdf/src/test/java/org/xbib/content/rdf/IRINamespaceCompactionTest.java index 86c2cb4..632f14b 100644 --- a/content-rdf/src/test/java/org/xbib/content/rdf/IRINamespaceCompactionTest.java +++ b/content-rdf/src/test/java/org/xbib/content/rdf/IRINamespaceCompactionTest.java @@ -1,14 +1,14 @@ package org.xbib.content.rdf; -import org.junit.Assert; -import org.junit.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.Test; import org.xbib.content.resource.IRI; import org.xbib.content.resource.IRINamespaceContext; /** * */ -public class IRINamespaceCompactionTest extends Assert { +public class IRINamespaceCompactionTest { @Test public void testCompaction() throws Exception { diff --git a/content-rdf/src/test/java/org/xbib/content/rdf/IRITest.java b/content-rdf/src/test/java/org/xbib/content/rdf/IRITest.java index a461d92..ed961ed 100644 --- a/content-rdf/src/test/java/org/xbib/content/rdf/IRITest.java +++ b/content-rdf/src/test/java/org/xbib/content/rdf/IRITest.java @@ -1,27 +1,32 @@ package org.xbib.content.rdf; -import org.junit.Assert; -import org.junit.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; import org.xbib.content.resource.IRI; import org.xbib.content.resource.IRISyntaxException; /** * */ -public class IRITest extends Assert { +public class IRITest { @Test public void testJsonLd() { IRI iri = IRI.create("@context"); - assertEquals(null, iri.getScheme()); + assertNull(iri.getScheme()); assertEquals("@context", iri.getSchemeSpecificPart()); } - @Test(expected = IRISyntaxException.class) + @Test public void testIllegalBlankNodeIRI() { - IRI iri = IRI.create("_:a1"); - assertEquals("_", iri.getScheme()); - assertEquals("a1", iri.getSchemeSpecificPart()); + Assertions.assertThrows(IRISyntaxException.class, () -> { + IRI iri = IRI.create("_:a1"); + assertEquals("_", iri.getScheme()); + assertEquals("a1", iri.getSchemeSpecificPart()); + + }); } @Test diff --git a/content-rdf/src/test/java/org/xbib/content/rdf/RdfXContentGeneratorTest.java b/content-rdf/src/test/java/org/xbib/content/rdf/RdfXContentGeneratorTest.java index 2fb50d5..d325a63 100644 --- a/content-rdf/src/test/java/org/xbib/content/rdf/RdfXContentGeneratorTest.java +++ b/content-rdf/src/test/java/org/xbib/content/rdf/RdfXContentGeneratorTest.java @@ -1,9 +1,9 @@ package org.xbib.content.rdf; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.xbib.content.rdf.RdfXContentFactory.rdfXContentBuilder; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.xbib.content.rdf.internal.DefaultLiteral; import org.xbib.content.rdf.internal.DefaultResource; import org.xbib.content.resource.IRI; @@ -11,7 +11,7 @@ import org.xbib.content.resource.IRI; /** * */ -public class RdfXContentGeneratorTest extends Assert { +public class RdfXContentGeneratorTest { @Test public void testContentBuilder() throws Exception { diff --git a/content-rdf/src/test/java/org/xbib/content/rdf/RouteRdfXContentBuilderTest.java b/content-rdf/src/test/java/org/xbib/content/rdf/RouteRdfXContentBuilderTest.java index ec47dec..3ddb2a7 100644 --- a/content-rdf/src/test/java/org/xbib/content/rdf/RouteRdfXContentBuilderTest.java +++ b/content-rdf/src/test/java/org/xbib/content/rdf/RouteRdfXContentBuilderTest.java @@ -1,13 +1,14 @@ package org.xbib.content.rdf; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.xbib.content.rdf.RdfXContentFactory.routeRdfXContentBuilder; +import static org.xbib.content.rdf.StreamTester.assertStream; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.xbib.content.rdf.internal.DefaultLiteral; import org.xbib.content.rdf.internal.DefaultResource; import org.xbib.content.rdf.io.rdfxml.RdfXmlContentParser; import org.xbib.content.resource.IRI; -import org.xbib.helper.StreamTester; import java.io.IOException; import java.io.InputStream; @@ -18,7 +19,7 @@ import java.nio.charset.StandardCharsets; /** * */ -public class RouteRdfXContentBuilderTest extends StreamTester { +public class RouteRdfXContentBuilderTest { @Test public void testRoute() throws Exception { diff --git a/content-rdf/src/test/java/org/xbib/helper/StreamTester.java b/content-rdf/src/test/java/org/xbib/content/rdf/StreamTester.java similarity index 65% rename from content-rdf/src/test/java/org/xbib/helper/StreamTester.java rename to content-rdf/src/test/java/org/xbib/content/rdf/StreamTester.java index 37295ee..34509e7 100644 --- a/content-rdf/src/test/java/org/xbib/helper/StreamTester.java +++ b/content-rdf/src/test/java/org/xbib/content/rdf/StreamTester.java @@ -1,26 +1,26 @@ -package org.xbib.helper; - -import org.junit.Assert; +package org.xbib.content.rdf; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; import java.io.InputStream; import java.io.Reader; /** * */ -public class StreamTester extends Assert { +public class StreamTester { - protected static void assertStream(InputStream expected, InputStream actual) { + public static void assertStream(InputStream expected, InputStream actual) { int offset = 0; try { while (true) { final int exp = expected.read(); if (exp == -1) { - assertEquals("Expecting end of actual stream at offset " + offset, -1, actual.read()); + assertEquals(-1, actual.read()); break; } else { final int act = actual.read(); - assertEquals("Expecting same data at offset " + offset, exp, act); + assertEquals(exp, act); } offset++; } @@ -37,11 +37,11 @@ public class StreamTester extends Assert { while (true) { final int exp = expected.read(); if (exp == -1) { - assertEquals("Expecting end of actual stream at offset " + offset, -1, actual.read()); + assertEquals(-1, actual.read(), "Expecting end of actual stream at offset " + offset); break; } else { final int act = actual.read(); - assertEquals("Expecting same data at offset " + offset, exp, act); + assertEquals(exp, act, "Expecting same data at offset " + offset); } offset++; } diff --git a/content-rdf/src/test/java/org/xbib/content/rdf/internal/BlankNodeTest.java b/content-rdf/src/test/java/org/xbib/content/rdf/internal/BlankNodeTest.java index 8f12119..1cf6258 100644 --- a/content-rdf/src/test/java/org/xbib/content/rdf/internal/BlankNodeTest.java +++ b/content-rdf/src/test/java/org/xbib/content/rdf/internal/BlankNodeTest.java @@ -1,7 +1,7 @@ package org.xbib.content.rdf.internal; -import org.junit.Assert; -import org.junit.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.Test; import org.xbib.content.rdf.Resource; import org.xbib.content.rdf.Triple; import org.xbib.content.resource.IRI; @@ -11,7 +11,7 @@ import java.util.Iterator; /** * */ -public class BlankNodeTest extends Assert { +public class BlankNodeTest { @Test public void testBlankNodeRenumbering() throws Exception { diff --git a/content-rdf/src/test/java/org/xbib/content/rdf/internal/LiteralTest.java b/content-rdf/src/test/java/org/xbib/content/rdf/internal/LiteralTest.java index ada8126..2fdbd04 100644 --- a/content-rdf/src/test/java/org/xbib/content/rdf/internal/LiteralTest.java +++ b/content-rdf/src/test/java/org/xbib/content/rdf/internal/LiteralTest.java @@ -1,13 +1,13 @@ package org.xbib.content.rdf.internal; -import org.junit.Assert; -import org.junit.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.Test; import org.xbib.content.resource.IRI; /** * */ -public class LiteralTest extends Assert { +public class LiteralTest { @Test public void testLiteral() { diff --git a/content-rdf/src/test/java/org/xbib/content/rdf/internal/ResourceTest.java b/content-rdf/src/test/java/org/xbib/content/rdf/internal/ResourceTest.java index 4912264..26fe152 100644 --- a/content-rdf/src/test/java/org/xbib/content/rdf/internal/ResourceTest.java +++ b/content-rdf/src/test/java/org/xbib/content/rdf/internal/ResourceTest.java @@ -1,9 +1,11 @@ package org.xbib.content.rdf.internal; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.xbib.content.rdf.RdfContentFactory.ntripleBuilder; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.xbib.content.rdf.Literal; import org.xbib.content.rdf.RdfContentBuilder; import org.xbib.content.rdf.Resource; @@ -19,16 +21,16 @@ import java.util.Iterator; /** * */ -public class ResourceTest extends Assert { +public class ResourceTest { @Test public void deleted() throws Exception { Resource r = new DefaultAnonymousResource(); - assertEquals(r.isDeleted(), false); + assertFalse(r.isDeleted()); r.setDeleted(true); - assertEquals(r.isDeleted(), true); + assertTrue(r.isDeleted()); r.setDeleted(false); - assertEquals(r.isDeleted(), false); + assertFalse(r.isDeleted()); } @Test @@ -44,7 +46,7 @@ public class ResourceTest extends Assert { @Test public void testEmptyResources() throws Exception { Resource r = new DefaultResource(IRI.create("urn:root")); - assertEquals(r.isEmpty(), true); + assertTrue(r.isEmpty()); assertEquals(r.toString(), "urn:root"); } @@ -52,14 +54,14 @@ public class ResourceTest extends Assert { public void testEmptyProperty() throws Exception { Resource r = new DefaultResource(IRI.create("urn:root")); r.add("urn:property", (String) null); - assertEquals(r.isEmpty(), true); + assertTrue(r.isEmpty()); } @Test public void testStringLiteral() throws Exception { Resource r = new DefaultResource(IRI.create("urn:root")); r.add("urn:property", "Hello World"); - assertEquals(r.isEmpty(), false); + assertFalse(r.isEmpty()); assertEquals(r.triples().get(0).object().toString(), "Hello World"); } @@ -68,7 +70,7 @@ public class ResourceTest extends Assert { Resource r = new DefaultResource(IRI.create("urn:root")); DefaultLiteral literal = new DefaultLiteral(123).type(Literal.INT); r.add("urn:property", literal); - assertEquals(r.isEmpty(), false); + assertFalse(r.isEmpty()); assertEquals(r.triples().get(0).object().toString(), "123^^xsd:int"); } diff --git a/content-rdf/src/test/java/org/xbib/content/rdf/internal/TripleTest.java b/content-rdf/src/test/java/org/xbib/content/rdf/internal/TripleTest.java index 564a25c..ad8dc38 100644 --- a/content-rdf/src/test/java/org/xbib/content/rdf/internal/TripleTest.java +++ b/content-rdf/src/test/java/org/xbib/content/rdf/internal/TripleTest.java @@ -1,7 +1,7 @@ package org.xbib.content.rdf.internal; -import org.junit.Assert; -import org.junit.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.Test; import org.xbib.content.rdf.Resource; import org.xbib.content.resource.IRI; import org.xbib.content.resource.Node; @@ -9,7 +9,7 @@ import org.xbib.content.resource.Node; /** * */ -public class TripleTest extends Assert { +public class TripleTest { @Test public void testSimpleTriple() { diff --git a/content-rdf/src/test/java/org/xbib/content/rdf/io/json/JsonReaderTest.java b/content-rdf/src/test/java/org/xbib/content/rdf/io/json/JsonReaderTest.java index af6d505..76daeb3 100644 --- a/content-rdf/src/test/java/org/xbib/content/rdf/io/json/JsonReaderTest.java +++ b/content-rdf/src/test/java/org/xbib/content/rdf/io/json/JsonReaderTest.java @@ -2,12 +2,13 @@ package org.xbib.content.rdf.io.json; import static org.xbib.content.rdf.RdfContentFactory.jsonBuilder; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.xbib.content.rdf.RdfContentBuilder; import org.xbib.content.rdf.io.xml.XmlHandler; import org.xbib.content.resource.IRI; import org.xbib.content.resource.IRINamespaceContext; -import org.xbib.helper.StreamTester; +import org.xbib.content.resource.NamespaceContext; +import org.xbib.content.rdf.StreamTester; import java.io.IOException; import java.io.InputStream; @@ -55,7 +56,7 @@ public class JsonReaderTest extends StreamTester { } @Override - public XmlHandler setNamespaceContext(IRINamespaceContext namespaceContext) { + public XmlHandler setNamespaceContext(NamespaceContext namespaceContext) { return this; } diff --git a/content-rdf/src/test/java/org/xbib/content/rdf/io/ntriple/NTripleReaderTest.java b/content-rdf/src/test/java/org/xbib/content/rdf/io/ntriple/NTripleReaderTest.java index 98b15fc..faf37ec 100644 --- a/content-rdf/src/test/java/org/xbib/content/rdf/io/ntriple/NTripleReaderTest.java +++ b/content-rdf/src/test/java/org/xbib/content/rdf/io/ntriple/NTripleReaderTest.java @@ -2,9 +2,9 @@ package org.xbib.content.rdf.io.ntriple; import static org.xbib.content.rdf.RdfContentFactory.ntripleBuilder; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.xbib.content.rdf.RdfContentBuilder; -import org.xbib.helper.StreamTester; +import org.xbib.content.rdf.StreamTester; import java.io.IOException; import java.io.InputStream; diff --git a/content-rdf/src/test/java/org/xbib/content/rdf/io/ntriple/NTripleTest.java b/content-rdf/src/test/java/org/xbib/content/rdf/io/ntriple/NTripleTest.java index 38bce65..ff79f14 100644 --- a/content-rdf/src/test/java/org/xbib/content/rdf/io/ntriple/NTripleTest.java +++ b/content-rdf/src/test/java/org/xbib/content/rdf/io/ntriple/NTripleTest.java @@ -1,9 +1,10 @@ package org.xbib.content.rdf.io.ntriple; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.xbib.content.rdf.RdfContentFactory.ntripleBuilder; -import org.junit.Assert; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.xbib.content.rdf.RdfContentBuilder; import org.xbib.content.rdf.Resource; import org.xbib.content.rdf.XSDResourceIdentifiers; @@ -14,7 +15,7 @@ import org.xbib.content.resource.IRI; /** * */ -public class NTripleTest extends Assert { +public class NTripleTest { @Test public void testNTripleBuilder() throws Exception { diff --git a/content-rdf/src/test/java/org/xbib/content/rdf/io/rdfxml/EuropeanaEDMReaderTest.java b/content-rdf/src/test/java/org/xbib/content/rdf/io/rdfxml/EuropeanaEDMReaderTest.java index ebd7260..487e396 100644 --- a/content-rdf/src/test/java/org/xbib/content/rdf/io/rdfxml/EuropeanaEDMReaderTest.java +++ b/content-rdf/src/test/java/org/xbib/content/rdf/io/rdfxml/EuropeanaEDMReaderTest.java @@ -2,8 +2,7 @@ package org.xbib.content.rdf.io.rdfxml; import static org.xbib.content.rdf.RdfContentFactory.ntripleBuilder; -import org.junit.Test; -import org.junit.experimental.categories.Category; +import org.junit.jupiter.api.Test; import org.xbib.content.rdf.RdfContent; import org.xbib.content.rdf.RdfContentBuilder; import org.xbib.content.rdf.Resource; @@ -11,12 +10,11 @@ import org.xbib.content.rdf.Triple; import org.xbib.content.rdf.internal.DefaultLiteral; import org.xbib.content.rdf.internal.DefaultRdfGraph; import org.xbib.content.rdf.internal.DefaultTriple; -import org.xbib.content.rdf.io.IOTests; import org.xbib.content.rdf.io.ntriple.NTripleContent; import org.xbib.content.rdf.io.ntriple.NTripleContentParams; import org.xbib.content.resource.IRI; import org.xbib.content.resource.Node; -import org.xbib.helper.StreamTester; +import org.xbib.content.rdf.StreamTester; import java.io.IOException; import java.io.InputStream; @@ -25,14 +23,12 @@ import java.util.Iterator; /** * */ -@Category(IOTests.class) public class EuropeanaEDMReaderTest extends StreamTester { private static final IRI GEO_LAT = IRI.create("http://www.w3.org/2003/01/geo/wgs84_pos#lat"); private static final IRI GEO_LON = IRI.create("http://www.w3.org/2003/01/geo/wgs84_pos#long"); private static final IRI location = IRI.create("location"); - @SuppressWarnings("unchecked") @Test public void testEuropeana() throws Exception { String filename = "oai_edm.xml"; @@ -56,7 +52,7 @@ public class EuropeanaEDMReaderTest extends StreamTester { builder.streamInput()); } - private class GeoJSONFilter extends RdfContentBuilder { + private static class GeoJSONFilter extends RdfContentBuilder { DefaultRdfGraph graph; diff --git a/content-rdf/src/test/java/org/xbib/content/rdf/io/rdfxml/GNDRdfXmlReaderTest.java b/content-rdf/src/test/java/org/xbib/content/rdf/io/rdfxml/GNDRdfXmlReaderTest.java index 9f026a1..beceeec 100644 --- a/content-rdf/src/test/java/org/xbib/content/rdf/io/rdfxml/GNDRdfXmlReaderTest.java +++ b/content-rdf/src/test/java/org/xbib/content/rdf/io/rdfxml/GNDRdfXmlReaderTest.java @@ -2,28 +2,22 @@ package org.xbib.content.rdf.io.rdfxml; import static org.xbib.content.rdf.RdfContentFactory.turtleBuilder; -import org.junit.Test; -import org.junit.experimental.categories.Category; +import org.junit.jupiter.api.Test; import org.xbib.content.rdf.RdfContentFactory; -import org.xbib.content.rdf.io.IOTests; import org.xbib.content.rdf.io.ntriple.NTripleContentParams; import org.xbib.content.rdf.io.turtle.TurtleContentParams; import org.xbib.content.resource.IRINamespaceContext; -import org.xbib.helper.StreamTester; +import org.xbib.content.rdf.StreamTester; import java.io.InputStream; import java.io.InputStreamReader; import java.io.StringReader; -import java.util.logging.Logger; /** * */ -@Category(IOTests.class) public class GNDRdfXmlReaderTest extends StreamTester { - private static final Logger logger = Logger.getLogger(GNDRdfXmlReaderTest.class.getName()); - @Test public void testGNDfromRdfXmltoTurtle() throws Exception { String filename = "GND.rdf"; diff --git a/content-rdf/src/test/java/org/xbib/content/rdf/io/rdfxml/RdfXmlReaderTest.java b/content-rdf/src/test/java/org/xbib/content/rdf/io/rdfxml/RdfXmlReaderTest.java index 1e77f0d..fc20063 100644 --- a/content-rdf/src/test/java/org/xbib/content/rdf/io/rdfxml/RdfXmlReaderTest.java +++ b/content-rdf/src/test/java/org/xbib/content/rdf/io/rdfxml/RdfXmlReaderTest.java @@ -2,28 +2,22 @@ package org.xbib.content.rdf.io.rdfxml; import static org.xbib.content.rdf.RdfContentFactory.turtleBuilder; -import org.junit.Test; -import org.junit.experimental.categories.Category; +import org.junit.jupiter.api.Test; import org.xbib.content.rdf.internal.DefaultAnonymousResource; -import org.xbib.content.rdf.io.IOTests; import org.xbib.content.rdf.io.turtle.TurtleContentParams; import org.xbib.content.resource.IRINamespaceContext; -import org.xbib.helper.StreamTester; +import org.xbib.content.rdf.StreamTester; import java.io.InputStream; import java.io.InputStreamReader; import java.io.StringReader; import java.nio.charset.StandardCharsets; -import java.util.logging.Logger; /** * */ -@Category(IOTests.class) public class RdfXmlReaderTest extends StreamTester { - private static final Logger logger = Logger.getLogger(RdfXmlReaderTest.class.getName()); - @Test public void testReader() throws Exception { String filename = "118540238.xml"; diff --git a/content-rdf/src/test/java/org/xbib/content/rdf/io/rdfxml/VIAFRdfXmlReaderTest.java b/content-rdf/src/test/java/org/xbib/content/rdf/io/rdfxml/VIAFRdfXmlReaderTest.java index 523894e..6d478f5 100644 --- a/content-rdf/src/test/java/org/xbib/content/rdf/io/rdfxml/VIAFRdfXmlReaderTest.java +++ b/content-rdf/src/test/java/org/xbib/content/rdf/io/rdfxml/VIAFRdfXmlReaderTest.java @@ -2,12 +2,10 @@ package org.xbib.content.rdf.io.rdfxml; import static org.xbib.content.rdf.RdfContentFactory.turtleBuilder; -import org.junit.Test; -import org.junit.experimental.categories.Category; -import org.xbib.content.rdf.io.IOTests; +import org.junit.jupiter.api.Test; import org.xbib.content.rdf.io.turtle.TurtleContentParams; import org.xbib.content.resource.IRINamespaceContext; -import org.xbib.helper.StreamTester; +import org.xbib.content.rdf.StreamTester; import java.io.IOException; import java.io.InputStream; @@ -17,7 +15,6 @@ import java.io.StringReader; /** * */ -@Category(IOTests.class) public class VIAFRdfXmlReaderTest extends StreamTester { @Test diff --git a/content-rdf/src/test/java/org/xbib/content/rdf/io/turtle/TurtleConformanceTest.java b/content-rdf/src/test/java/org/xbib/content/rdf/io/turtle/TurtleConformanceTest.java index 5220125..6c269be 100644 --- a/content-rdf/src/test/java/org/xbib/content/rdf/io/turtle/TurtleConformanceTest.java +++ b/content-rdf/src/test/java/org/xbib/content/rdf/io/turtle/TurtleConformanceTest.java @@ -1,22 +1,18 @@ package org.xbib.content.rdf.io.turtle; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.xbib.content.rdf.RdfContentFactory; import org.xbib.content.resource.IRI; -import org.xbib.helper.StreamTester; +import org.xbib.content.rdf.StreamTester; import java.io.InputStream; import java.text.MessageFormat; -import java.util.logging.Level; -import java.util.logging.Logger; /** * */ public class TurtleConformanceTest extends StreamTester { - private static final Logger logger = Logger.getLogger(TurtleConformanceTest.class.getName()); - @Test public void conformance() throws Exception { for (int n = 0; n < 30; n++) { @@ -26,10 +22,9 @@ public class TurtleConformanceTest extends StreamTester { .setBaseIRI(IRI.create("http://example/base/")); turtleParser.setRdfContentBuilderProvider(RdfContentFactory::turtleBuilder); turtleParser.setRdfContentBuilderHandler(b -> { - logger.log(Level.INFO, MessageFormat.format("turtle test {0}", b.string())); + //logger.log(Level.INFO, MessageFormat.format("turtle test {0}", b.string())); }); turtleParser.parse(); } } - } diff --git a/content-rdf/src/test/java/org/xbib/content/rdf/io/turtle/TurtleTest.java b/content-rdf/src/test/java/org/xbib/content/rdf/io/turtle/TurtleTest.java index 4295ea2..7de319f 100644 --- a/content-rdf/src/test/java/org/xbib/content/rdf/io/turtle/TurtleTest.java +++ b/content-rdf/src/test/java/org/xbib/content/rdf/io/turtle/TurtleTest.java @@ -1,17 +1,17 @@ package org.xbib.content.rdf.io.turtle; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.xbib.content.rdf.RdfContentFactory.turtleBuilder; -import org.junit.Test; -import org.junit.experimental.categories.Category; +import org.junit.jupiter.api.Test; import org.xbib.content.rdf.RdfContentBuilder; import org.xbib.content.rdf.RdfContentFactory; import org.xbib.content.rdf.Resource; import org.xbib.content.rdf.internal.DefaultResource; -import org.xbib.content.rdf.io.IOTests; import org.xbib.content.resource.IRI; import org.xbib.content.resource.IRINamespaceContext; -import org.xbib.helper.StreamTester; +import org.xbib.content.resource.NamespaceContext; +import org.xbib.content.rdf.StreamTester; import java.io.BufferedReader; import java.io.InputStream; @@ -21,12 +21,11 @@ import java.nio.charset.StandardCharsets; /** * */ -@Category(IOTests.class) public class TurtleTest extends StreamTester { @Test public void testTurtleGND() throws Exception { - IRINamespaceContext context = IRINamespaceContext.newInstance(); + NamespaceContext context = IRINamespaceContext.newInstance(); context.addNamespace("gnd", "http://d-nb.info/gnd/"); InputStream in = getClass().getResourceAsStream("GND.ttl"); TurtleContentParser reader = new TurtleContentParser(in) diff --git a/content-rdf/src/test/java/org/xbib/content/rdf/io/xml/OAITest.java b/content-rdf/src/test/java/org/xbib/content/rdf/io/xml/OAITest.java index 634356d..f6ed259 100644 --- a/content-rdf/src/test/java/org/xbib/content/rdf/io/xml/OAITest.java +++ b/content-rdf/src/test/java/org/xbib/content/rdf/io/xml/OAITest.java @@ -2,21 +2,18 @@ package org.xbib.content.rdf.io.xml; import static org.xbib.content.rdf.RdfContentFactory.turtleBuilder; -import org.junit.Test; -import org.junit.experimental.categories.Category; +import org.junit.jupiter.api.Test; import org.xbib.content.rdf.RdfContentBuilder; -import org.xbib.content.rdf.io.IOTests; import org.xbib.content.rdf.io.turtle.TurtleContentParams; import org.xbib.content.resource.IRI; import org.xbib.content.resource.IRINamespaceContext; -import org.xbib.helper.StreamTester; +import org.xbib.content.resource.NamespaceContext; +import org.xbib.content.rdf.StreamTester; import org.xbib.net.PercentEncoders; import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; -import java.util.logging.Level; -import java.util.logging.Logger; import javax.xml.namespace.QName; @@ -25,10 +22,7 @@ import javax.xml.namespace.QName; */ public class OAITest extends StreamTester { - private static final Logger logger = Logger.getLogger(OAITest.class.getName()); - @Test - @Category(IOTests.class) public void testOAIListRecordsToTurtle() throws Exception { String filename = "oai-listrecords.xml"; InputStream in = getClass().getResourceAsStream(filename); @@ -38,7 +32,7 @@ public class OAITest extends StreamTester { IRINamespaceContext context = IRINamespaceContext.newInstance(); XmlContentParams params = new XmlContentParams(context); - XmlHandler xmlHandler = new AbstractXmlResourceHandler(params) { + XmlHandler xmlHandler = new AbstractXmlResourceHandler<>(params) { @Override public boolean isResourceDelimiter(QName name) { @@ -53,7 +47,7 @@ public class OAITest extends StreamTester { getResource().setId(IRI.create("id:" + PercentEncoders.getRegNameEncoder(StandardCharsets.UTF_8).encode(value))); } catch (IOException e) { - logger.log(Level.FINE, e.getMessage(), e); + // ignore } } } @@ -64,7 +58,7 @@ public class OAITest extends StreamTester { } @Override - public XmlHandler setNamespaceContext(IRINamespaceContext namespaceContext) { + public XmlHandler setNamespaceContext(NamespaceContext namespaceContext) { return this; } diff --git a/content-rdf/src/test/java/org/xbib/content/rdf/io/xml/XmlReaderTest.java b/content-rdf/src/test/java/org/xbib/content/rdf/io/xml/XmlReaderTest.java index b28da42..df2b81c 100644 --- a/content-rdf/src/test/java/org/xbib/content/rdf/io/xml/XmlReaderTest.java +++ b/content-rdf/src/test/java/org/xbib/content/rdf/io/xml/XmlReaderTest.java @@ -1,21 +1,21 @@ package org.xbib.content.rdf.io.xml; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.xbib.content.rdf.RdfContentFactory.turtleBuilder; -import org.junit.Test; -import org.junit.experimental.categories.Category; +import org.junit.jupiter.api.Test; import org.xbib.content.rdf.RdfContentBuilder; import org.xbib.content.rdf.Resource; import org.xbib.content.rdf.Triple; import org.xbib.content.rdf.internal.DefaultAnonymousResource; import org.xbib.content.rdf.internal.DefaultResource; -import org.xbib.content.rdf.io.IOTests; import org.xbib.content.rdf.io.ntriple.NTripleContent; import org.xbib.content.rdf.io.ntriple.NTripleContentParams; import org.xbib.content.rdf.io.turtle.TurtleContentParams; import org.xbib.content.resource.IRI; import org.xbib.content.resource.IRINamespaceContext; -import org.xbib.helper.StreamTester; +import org.xbib.content.resource.NamespaceContext; +import org.xbib.content.rdf.StreamTester; import org.xbib.net.PercentEncoders; import java.io.IOException; @@ -23,19 +23,14 @@ import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.util.LinkedList; import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; import javax.xml.namespace.QName; /** * */ -@Category(IOTests.class) public class XmlReaderTest extends StreamTester { - private static final Logger logger = Logger.getLogger(XmlReaderTest.class.getName()); - @Test public void testOAIDC() throws Exception { String filename = "oro-eprint-25656.xml"; @@ -49,7 +44,7 @@ public class XmlReaderTest extends StreamTester { namespaceContext.addNamespace("dc", "http://purl.org/dc/elements/1.1/"); XmlContentParams params = new XmlContentParams(namespaceContext); - XmlHandler xmlHandler = new AbstractXmlResourceHandler(params) { + XmlHandler xmlHandler = new AbstractXmlResourceHandler<>(params) { @Override public boolean isResourceDelimiter(QName name) { @@ -64,7 +59,7 @@ public class XmlReaderTest extends StreamTester { getResource().setId(IRI.create("id:" + PercentEncoders.getRegNameEncoder(StandardCharsets.UTF_8).encode(value))); } catch (IOException e) { - logger.log(Level.FINE, e.getMessage(), e); + // swallow } } } @@ -76,7 +71,7 @@ public class XmlReaderTest extends StreamTester { } @Override - public XmlHandler setNamespaceContext(IRINamespaceContext namespaceContext) { + public XmlHandler setNamespaceContext(NamespaceContext namespaceContext) { return this; } @@ -104,7 +99,7 @@ public class XmlReaderTest extends StreamTester { } IRINamespaceContext namespaceContext = IRINamespaceContext.newInstance(); XmlContentParams params = new XmlContentParams(namespaceContext); - AbstractXmlHandler xmlHandler = new AbstractXmlResourceHandler(params) { + AbstractXmlHandler xmlHandler = new AbstractXmlResourceHandler<>(params) { @Override public boolean isResourceDelimiter(QName name) { @@ -122,7 +117,7 @@ public class XmlReaderTest extends StreamTester { } @Override - public XmlHandler setNamespaceContext(IRINamespaceContext namespaceContext) { + public XmlHandler setNamespaceContext(NamespaceContext namespaceContext) { return this; } @@ -153,7 +148,7 @@ public class XmlReaderTest extends StreamTester { } IRINamespaceContext namespaceContext = IRINamespaceContext.newInstance(); XmlContentParams params = new XmlContentParams(namespaceContext); - AbstractXmlHandler xmlHandler = new AbstractXmlResourceHandler(params) { + AbstractXmlHandler xmlHandler = new AbstractXmlResourceHandler<>(params) { @Override public boolean isResourceDelimiter(QName name) { return false; @@ -170,7 +165,7 @@ public class XmlReaderTest extends StreamTester { } @Override - public XmlHandler setNamespaceContext(IRINamespaceContext namespaceContext) { + public XmlHandler setNamespaceContext(NamespaceContext namespaceContext) { return this; } @@ -194,7 +189,7 @@ public class XmlReaderTest extends StreamTester { ); } - private class MyBuilder extends RdfContentBuilder { + private static class MyBuilder extends RdfContentBuilder { final List triples = new LinkedList<>(); diff --git a/content-rdf/src/test/java/org/xbib/content/rdf/io/xml/XmlResourceWriterTest.java b/content-rdf/src/test/java/org/xbib/content/rdf/io/xml/XmlResourceWriterTest.java index 0f7afdd..615920f 100644 --- a/content-rdf/src/test/java/org/xbib/content/rdf/io/xml/XmlResourceWriterTest.java +++ b/content-rdf/src/test/java/org/xbib/content/rdf/io/xml/XmlResourceWriterTest.java @@ -1,22 +1,19 @@ package org.xbib.content.rdf.io.xml; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.xbib.content.rdf.RdfContentFactory.xmlBuilder; -import org.junit.Assert; -import org.junit.Test; -import org.junit.experimental.categories.Category; +import org.junit.jupiter.api.Test; import org.xbib.content.rdf.RdfContentBuilder; import org.xbib.content.rdf.Resource; import org.xbib.content.rdf.internal.DefaultAnonymousResource; import org.xbib.content.rdf.internal.DefaultResource; -import org.xbib.content.rdf.io.IOTests; import org.xbib.content.resource.IRI; /** * */ -@Category(IOTests.class) -public class XmlResourceWriterTest extends Assert { +public class XmlResourceWriterTest { @Test public void testXMLResourceWriter() throws Exception { diff --git a/content-rdf/src/test/java/org/xbib/content/rdf/util/MultiMapTest.java b/content-rdf/src/test/java/org/xbib/content/rdf/util/MultiMapTest.java index 249ed57..fd04e66 100644 --- a/content-rdf/src/test/java/org/xbib/content/rdf/util/MultiMapTest.java +++ b/content-rdf/src/test/java/org/xbib/content/rdf/util/MultiMapTest.java @@ -1,10 +1,8 @@ package org.xbib.content.rdf.util; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import org.junit.Test; - +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import org.junit.jupiter.api.Test; import java.util.Arrays; /** diff --git a/content-rdf/src/test/java/org/xbib/helper/package-info.java b/content-rdf/src/test/java/org/xbib/helper/package-info.java deleted file mode 100644 index bc4f6a8..0000000 --- a/content-rdf/src/test/java/org/xbib/helper/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * Classes for helpting the testing of RDF content. - */ -package org.xbib.helper; diff --git a/content-resource/build.gradle b/content-resource/build.gradle index 3a626c6..a9255cd 100644 --- a/content-resource/build.gradle +++ b/content-resource/build.gradle @@ -1,4 +1,4 @@ dependencies { - compile "org.xbib:net-url:${project.property('xbib-net.version')}" - testCompile "com.fasterxml.jackson.core:jackson-databind:${project.property('jackson.version')}" + api "org.xbib:net-url:${project.property('xbib.net.version')}" + testImplementation "com.fasterxml.jackson.core:jackson-databind:${project.property('jackson.version')}" } \ No newline at end of file diff --git a/content-resource/src/main/java/module-info.java b/content-resource/src/main/java/module-info.java new file mode 100644 index 0000000..77b1593 --- /dev/null +++ b/content-resource/src/main/java/module-info.java @@ -0,0 +1,5 @@ +module org.xbib.content.resource { + exports org.xbib.content.resource; + exports org.xbib.content.resource.text; + requires org.xbib.net.url; +} \ No newline at end of file diff --git a/content-resource/src/main/java/org/xbib/content/resource/IRINamespaceContext.java b/content-resource/src/main/java/org/xbib/content/resource/IRINamespaceContext.java index a32d13d..ed1f0a0 100644 --- a/content-resource/src/main/java/org/xbib/content/resource/IRINamespaceContext.java +++ b/content-resource/src/main/java/org/xbib/content/resource/IRINamespaceContext.java @@ -1,36 +1,39 @@ package org.xbib.content.resource; import java.util.ArrayList; +import java.util.Enumeration; +import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.MissingResourceException; import java.util.ResourceBundle; +import java.util.Set; +import java.util.SortedMap; +import java.util.TreeMap; /** * */ -public final class IRINamespaceContext extends XmlNamespaceContext { +public final class IRINamespaceContext implements NamespaceContext { - /** - * Share namespace.properties with {@link XmlNamespaceContext}. - */ private static final String DEFAULT_RESOURCE = - XmlNamespaceContext.class.getPackage().getName().replace('.', '/') + '/' + "namespace"; + IRINamespaceContext.class.getPackage().getName().replace('.', '/') + '/' + "namespace"; private static IRINamespaceContext instance; private static final IRINamespaceContext DEFAULT_CONTEXT = newInstance(DEFAULT_RESOURCE); + // sort namespace by length in descending order, useful for compacting prefix + private final SortedMap namespaces; + + private final SortedMap> prefixes; + + protected final Object lock; + private List sortedNamespacesByPrefixLength; - private IRINamespaceContext() { - super(); - } - - private IRINamespaceContext(ResourceBundle bundle) { - super(bundle); - } public static IRINamespaceContext getInstance() { return DEFAULT_CONTEXT; @@ -55,9 +58,36 @@ public final class IRINamespaceContext extends XmlNamespaceContext { return new IRINamespaceContext(); } + protected IRINamespaceContext() { + this.namespaces = new TreeMap<>(); + this.prefixes = new TreeMap<>(); + this.lock = new Object(); + } + + private IRINamespaceContext(ResourceBundle bundle) { + this(); + Enumeration en = bundle.getKeys(); + while (en.hasMoreElements()) { + String prefix = en.nextElement(); + String namespace = bundle.getString(prefix); + addNamespace(prefix, namespace); + } + } + @Override public void addNamespace(String prefix, String namespace) { - super.addNamespace(prefix, namespace); + if (prefix != null && namespace != null) { + synchronized (lock) { + namespaces.put(prefix, namespace); + if (prefixes.containsKey(namespace)) { + prefixes.get(namespace).add(prefix); + } else { + Set set = new HashSet<>(); + set.add(prefix); + prefixes.put(namespace, set); + } + } + } synchronized (lock) { sortedNamespacesByPrefixLength = new ArrayList<>(getNamespaces().values()); // sort from longest to shortest prefix for successful matching @@ -71,7 +101,7 @@ public final class IRINamespaceContext extends XmlNamespaceContext { public IRINamespaceContext add(Map map) { for (Map.Entry e : map.entrySet()) { - super.addNamespace(e.getKey(), e.getValue()); + addNamespace(e.getKey(), e.getValue()); } synchronized (lock) { sortedNamespacesByPrefixLength = new ArrayList<>(getNamespaces().values()); @@ -131,4 +161,37 @@ public final class IRINamespaceContext extends XmlNamespaceContext { public String getPrefix(IRI uri) { return getNamespaceURI(uri.getScheme()) != null ? uri.getScheme() : getPrefix(uri.toString()); } + + @Override + public SortedMap getNamespaces() { + return namespaces; + } + + @Override + public String getNamespaceURI(String prefix) { + if (prefix == null) { + return null; + } + return namespaces.getOrDefault(prefix, null); + } + + @Override + public String getPrefix(String namespaceURI) { + Iterator it = getPrefixes(namespaceURI); + return it != null && it.hasNext() ? it.next() : null; + } + + @Override + public Iterator getPrefixes(String namespace) { + if (namespace == null) { + throw new IllegalArgumentException("namespace URI cannot be null"); + } + return prefixes.containsKey(namespace) ? + prefixes.get(namespace).iterator() : null; + } + + @Override + public String toString() { + return namespaces.toString(); + } } diff --git a/content-resource/src/main/java/org/xbib/content/resource/NamespaceContext.java b/content-resource/src/main/java/org/xbib/content/resource/NamespaceContext.java new file mode 100644 index 0000000..976aeb1 --- /dev/null +++ b/content-resource/src/main/java/org/xbib/content/resource/NamespaceContext.java @@ -0,0 +1,17 @@ +package org.xbib.content.resource; + +import java.util.Iterator; +import java.util.SortedMap; + +public interface NamespaceContext { + + String getNamespaceURI(String prefix); + + String getPrefix(String namespaceURI); + + Iterator getPrefixes(String namespaceURI); + + SortedMap getNamespaces(); + + void addNamespace(String prefix, String namespace); +} diff --git a/content-smile/build.gradle b/content-smile/build.gradle index df5ed6f..6b4f9af 100644 --- a/content-smile/build.gradle +++ b/content-smile/build.gradle @@ -1,4 +1,4 @@ dependencies { - compile project(':content-core') - compile "com.fasterxml.jackson.dataformat:jackson-dataformat-smile:${project.property('jackson.version')}" + implementation project(':content-core') + api "com.fasterxml.jackson.dataformat:jackson-dataformat-smile:${project.property('jackson.version')}" } diff --git a/content-smile/src/main/java/module-info.java b/content-smile/src/main/java/module-info.java new file mode 100644 index 0000000..953910f --- /dev/null +++ b/content-smile/src/main/java/module-info.java @@ -0,0 +1,7 @@ +module org.xbib.content.smile { + exports org.xbib.content.smile; + requires org.xbib.content.core; + requires com.fasterxml.jackson.dataformat.smile; + provides org.xbib.content.XContent with + org.xbib.content.smile.SmileXContent; +} diff --git a/content-xml/build.gradle b/content-xml/build.gradle index d618b1d..07f88f6 100644 --- a/content-xml/build.gradle +++ b/content-xml/build.gradle @@ -1,7 +1,6 @@ dependencies { - compile project(':content-core') - compile project(':content-resource') - compile "com.fasterxml.jackson.dataformat:jackson-dataformat-xml:${project.property('jackson.version')}" - compile "com.fasterxml.jackson.core:jackson-databind:${project.property('jackson-databind.version')}" - compile "com.fasterxml.woodstox:woodstox-core:${project.property('woodstox.version')}" + implementation project(':content-core') + implementation project(':content-resource') + api "com.fasterxml.jackson.dataformat:jackson-dataformat-xml:${project.property('jackson.version')}" + implementation "com.fasterxml.woodstox:woodstox-core:${project.property('woodstox.version')}" } diff --git a/content-xml/src/main/java/module-info.java b/content-xml/src/main/java/module-info.java new file mode 100644 index 0000000..fae3918 --- /dev/null +++ b/content-xml/src/main/java/module-info.java @@ -0,0 +1,15 @@ +module org.xbib.content.xml { + exports org.xbib.content.xml; + exports org.xbib.content.xml.json; + exports org.xbib.content.xml.json.events; + exports org.xbib.content.xml.stream; + exports org.xbib.content.xml.transform; + exports org.xbib.content.xml.util; + requires java.xml; + requires org.xbib.content.core; + requires org.xbib.content.resource; + requires com.fasterxml.jackson.core; + requires com.fasterxml.jackson.dataformat.xml; + provides org.xbib.content.XContent with + org.xbib.content.xml.XmlXContent; +} diff --git a/content-resource/src/main/java/org/xbib/content/resource/XmlNamespaceContext.java b/content-xml/src/main/java/org/xbib/content/xml/XmlNamespaceContext.java similarity index 74% rename from content-resource/src/main/java/org/xbib/content/resource/XmlNamespaceContext.java rename to content-xml/src/main/java/org/xbib/content/xml/XmlNamespaceContext.java index 24394ec..0d57f32 100644 --- a/content-resource/src/main/java/org/xbib/content/resource/XmlNamespaceContext.java +++ b/content-xml/src/main/java/org/xbib/content/xml/XmlNamespaceContext.java @@ -1,4 +1,4 @@ -package org.xbib.content.resource; +package org.xbib.content.xml; import java.util.Enumeration; import java.util.HashSet; @@ -15,12 +15,7 @@ import javax.xml.namespace.NamespaceContext; /** * Contains a simple context for XML namespaces. */ -public class XmlNamespaceContext implements NamespaceContext { - - private static final String DEFAULT_RESOURCE = - XmlNamespaceContext.class.getPackage().getName().replace('.', '/') + '/' + "namespace"; - - private static final XmlNamespaceContext DEFAULT_CONTEXT = newDefaultInstance(); +public class XmlNamespaceContext implements NamespaceContext, org.xbib.content.resource.NamespaceContext { // sort namespace by length in descending order, useful for compacting prefix private final SortedMap namespaces; @@ -45,10 +40,6 @@ public class XmlNamespaceContext implements NamespaceContext { } } - public static XmlNamespaceContext getInstance() { - return DEFAULT_CONTEXT; - } - /** * Empty namespace context. * @@ -58,22 +49,10 @@ public class XmlNamespaceContext implements NamespaceContext { return new XmlNamespaceContext(); } - public static XmlNamespaceContext newDefaultInstance() { - return newInstance(DEFAULT_RESOURCE); - } - - /** - * Use thread context class laoder to instantiate a namespace context. - * @param bundleName the resource bundle name - * @return XML namespace context - */ - public static XmlNamespaceContext newInstance(String bundleName) { - return newInstance(bundleName, Locale.getDefault(), Thread.currentThread().getContextClassLoader()); - } - public static XmlNamespaceContext newInstance(String bundleName, Locale locale, ClassLoader classLoader) { try { - return new XmlNamespaceContext(ResourceBundle.getBundle(bundleName, locale, classLoader)); + ResourceBundle bundle = ResourceBundle.getBundle(bundleName, locale, classLoader); + return new XmlNamespaceContext(bundle); } catch (MissingResourceException e) { return new XmlNamespaceContext(); } diff --git a/content-xml/src/main/java/org/xbib/content/xml/XmlXContentGenerator.java b/content-xml/src/main/java/org/xbib/content/xml/XmlXContentGenerator.java index f2bd16a..b8c53d9 100644 --- a/content-xml/src/main/java/org/xbib/content/xml/XmlXContentGenerator.java +++ b/content-xml/src/main/java/org/xbib/content/xml/XmlXContentGenerator.java @@ -17,8 +17,6 @@ import java.io.IOException; import java.io.OutputStream; import java.math.BigDecimal; import java.math.BigInteger; -import java.util.logging.Level; -import java.util.logging.Logger; import javax.xml.namespace.NamespaceContext; import javax.xml.namespace.QName; @@ -29,8 +27,6 @@ import javax.xml.stream.XMLStreamException; */ public class XmlXContentGenerator extends AbstractXContentGenerator { - private static final Logger logger = Logger.getLogger(XmlXContentGenerator.class.getName()); - private final XmlXContentGeneratorDelegate delegate; private XmlXParams params; @@ -50,7 +46,7 @@ public class XmlXContentGenerator extends AbstractXContentGenerator { return params; } - public XmlXContentGenerator setParams(XmlXParams params) { + public XmlXContentGenerator setParams(XmlXParams params) throws IOException { delegate.setParams(params); return this; } @@ -138,12 +134,12 @@ public class XmlXContentGenerator extends AbstractXContentGenerator { this.params = params; } - public void setParams(XmlXParams params) { + public void setParams(XmlXParams params) throws IOException { this.params = params; try { generator.getStaxWriter().setPrefix(params.getRoot().getPrefix(), params.getRoot().getNamespaceURI()); } catch (XMLStreamException e) { - logger.log(Level.SEVERE, e.getMessage(), e); + throw new IOException(e); } } @@ -183,7 +179,7 @@ public class XmlXContentGenerator extends AbstractXContentGenerator { generator.getStaxWriter().writeNamespace(prefix, uri); } } catch (XMLStreamException e) { - logger.log(Level.SEVERE, e.getMessage(), e); + throw new IOException(e); } rootUsed = true; } diff --git a/content-xml/src/main/java/org/xbib/content/xml/XmlXParams.java b/content-xml/src/main/java/org/xbib/content/xml/XmlXParams.java index 92829e3..4f125b7 100644 --- a/content-xml/src/main/java/org/xbib/content/xml/XmlXParams.java +++ b/content-xml/src/main/java/org/xbib/content/xml/XmlXParams.java @@ -2,10 +2,6 @@ package org.xbib.content.xml; import com.fasterxml.jackson.dataformat.xml.XmlFactory; import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator; -import org.xbib.content.resource.XmlNamespaceContext; - -import java.util.logging.Level; -import java.util.logging.Logger; import javax.xml.namespace.QName; import javax.xml.stream.XMLInputFactory; @@ -16,8 +12,6 @@ import javax.xml.stream.XMLOutputFactory; */ public class XmlXParams { - private static final Logger logger = Logger.getLogger(XmlXParams.class.getName()); - private static final XmlXParams DEFAULT_PARAMS = new XmlXParams(new QName("root"), XmlNamespaceContext.newInstance(), @@ -69,35 +63,23 @@ public class XmlXParams { // load from service factories in META-INF/services // default impl is "com.sun.xml.internal.stream.XMLInputFactoryImpl" XMLInputFactory inputFactory = XMLInputFactory.newInstance(); - try { - inputFactory.setProperty("javax.xml.stream.isNamespaceAware", Boolean.TRUE); - inputFactory.setProperty("javax.xml.stream.isValidating", Boolean.FALSE); - inputFactory.setProperty("javax.xml.stream.isCoalescing", Boolean.TRUE); - inputFactory.setProperty("javax.xml.stream.isReplacingEntityReferences", Boolean.FALSE); - inputFactory.setProperty("javax.xml.stream.isSupportingExternalEntities", Boolean.FALSE); - } catch (Exception e) { - logger.log(Level.SEVERE, e.getMessage(), e); - } + inputFactory.setProperty("javax.xml.stream.isNamespaceAware", Boolean.TRUE); + inputFactory.setProperty("javax.xml.stream.isValidating", Boolean.FALSE); + inputFactory.setProperty("javax.xml.stream.isCoalescing", Boolean.TRUE); + inputFactory.setProperty("javax.xml.stream.isReplacingEntityReferences", Boolean.FALSE); + inputFactory.setProperty("javax.xml.stream.isSupportingExternalEntities", Boolean.FALSE); return inputFactory; } protected static XMLOutputFactory createXMLOutputFactory() { XMLOutputFactory outputFactory = XMLOutputFactory.newInstance(); - try { - outputFactory.setProperty("javax.xml.stream.isRepairingNamespaces", Boolean.FALSE); - } catch (Exception e) { - logger.log(Level.SEVERE, e.getMessage(), e); - } + outputFactory.setProperty("javax.xml.stream.isRepairingNamespaces", Boolean.FALSE); return outputFactory; } protected static XmlFactory createXmlFactory(XMLInputFactory inputFactory, XMLOutputFactory outputFactory) { XmlFactory xmlFactory = new XmlFactory(inputFactory, outputFactory); - try { - xmlFactory.configure(ToXmlGenerator.Feature.WRITE_XML_1_1, true); - } catch (Exception e) { - logger.log(Level.SEVERE, e.getMessage(), e); - } + xmlFactory.configure(ToXmlGenerator.Feature.WRITE_XML_1_1, true); return xmlFactory; } diff --git a/content-xml/src/main/java/org/xbib/content/xml/json/JsonSaxAdapter.java b/content-xml/src/main/java/org/xbib/content/xml/json/JsonSaxAdapter.java index fc91d6f..553e183 100644 --- a/content-xml/src/main/java/org/xbib/content/xml/json/JsonSaxAdapter.java +++ b/content-xml/src/main/java/org/xbib/content/xml/json/JsonSaxAdapter.java @@ -11,7 +11,7 @@ import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; -import org.xbib.content.resource.XmlNamespaceContext; +import org.xbib.content.resource.NamespaceContext; import org.xbib.content.xml.util.ToQName; import org.xml.sax.ContentHandler; import org.xml.sax.Locator; @@ -51,7 +51,7 @@ public class JsonSaxAdapter { private QName root = new QName("root"); - private XmlNamespaceContext context = XmlNamespaceContext.newDefaultInstance(); + private NamespaceContext context; public JsonSaxAdapter(Reader reader, ContentHandler contentHandler) throws IOException { this(factory.createParser(reader), contentHandler); @@ -68,7 +68,7 @@ public class JsonSaxAdapter { return this; } - public JsonSaxAdapter context(XmlNamespaceContext context) { + public JsonSaxAdapter context(NamespaceContext context) { this.context = context; return this; } @@ -163,7 +163,7 @@ public class JsonSaxAdapter { qname.getLocalPart(), qname.getPrefix() + ":" + qname.getLocalPart()); } - private void writeNamespaceDeclarations(XmlNamespaceContext context) throws SAXException { + private void writeNamespaceDeclarations(NamespaceContext context) throws SAXException { Set keys = new TreeSet<>(context.getNamespaces().keySet()); if (root != null && !keys.contains(root.getPrefix())) { contentHandler.startPrefixMapping(root.getPrefix(), root.getNamespaceURI()); diff --git a/content-xml/src/main/java/org/xbib/content/xml/json/JsonStylesheet.java b/content-xml/src/main/java/org/xbib/content/xml/json/JsonStylesheet.java index 604564e..3630d1f 100644 --- a/content-xml/src/main/java/org/xbib/content/xml/json/JsonStylesheet.java +++ b/content-xml/src/main/java/org/xbib/content/xml/json/JsonStylesheet.java @@ -1,6 +1,6 @@ package org.xbib.content.xml.json; -import org.xbib.content.resource.XmlNamespaceContext; +import org.xbib.content.xml.XmlNamespaceContext; import org.xbib.content.xml.transform.StylesheetTransformer; import org.xml.sax.InputSource; @@ -9,6 +9,7 @@ import java.io.InputStream; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Writer; +import java.nio.charset.StandardCharsets; import java.util.Arrays; import javax.xml.namespace.QName; @@ -24,7 +25,7 @@ public class JsonStylesheet { private QName root = new QName("root"); - private XmlNamespaceContext context = XmlNamespaceContext.newDefaultInstance(); + private XmlNamespaceContext context; private StylesheetTransformer transformer; @@ -51,7 +52,7 @@ public class JsonStylesheet { } public JsonStylesheet transform(InputStream in, OutputStream out) throws IOException { - return transform(in, new OutputStreamWriter(out, "UTF-8")); + return transform(in, new OutputStreamWriter(out, StandardCharsets.UTF_8)); } public JsonStylesheet transform(InputStream in, Writer out) throws IOException { @@ -78,7 +79,7 @@ public class JsonStylesheet { } public JsonStylesheet toXML(InputStream in, OutputStream out) throws IOException { - return toXML(in, new OutputStreamWriter(out, "UTF-8")); + return toXML(in, new OutputStreamWriter(out, StandardCharsets.UTF_8)); } public JsonStylesheet toXML(InputStream in, Writer out) throws IOException { diff --git a/content-xml/src/main/java/org/xbib/content/xml/json/JsonXmlReader.java b/content-xml/src/main/java/org/xbib/content/xml/json/JsonXmlReader.java index d3fe5bd..5910757 100644 --- a/content-xml/src/main/java/org/xbib/content/xml/json/JsonXmlReader.java +++ b/content-xml/src/main/java/org/xbib/content/xml/json/JsonXmlReader.java @@ -1,6 +1,6 @@ package org.xbib.content.xml.json; -import org.xbib.content.resource.XmlNamespaceContext; +import org.xbib.content.xml.XmlNamespaceContext; import org.xml.sax.ContentHandler; import org.xml.sax.DTDHandler; import org.xml.sax.EntityResolver; @@ -33,9 +33,9 @@ public class JsonXmlReader implements XMLReader { private QName root = new QName("root"); - private XmlNamespaceContext context = XmlNamespaceContext.newDefaultInstance(); + private XmlNamespaceContext context; - private Map map = new HashMap<>(); + private final Map map; private ContentHandler contentHandler; @@ -45,6 +45,10 @@ public class JsonXmlReader implements XMLReader { private ErrorHandler errorHandler; + public JsonXmlReader() { + this.map = new HashMap<>(); + } + public JsonXmlReader root(QName root) { this.root = root; return this; diff --git a/content-xml/src/main/java/org/xbib/content/xml/json/JsonXmlStreamer.java b/content-xml/src/main/java/org/xbib/content/xml/json/JsonXmlStreamer.java index 9889e93..a1a1baf 100644 --- a/content-xml/src/main/java/org/xbib/content/xml/json/JsonXmlStreamer.java +++ b/content-xml/src/main/java/org/xbib/content/xml/json/JsonXmlStreamer.java @@ -4,7 +4,8 @@ import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; -import org.xbib.content.resource.XmlNamespaceContext; +import org.xbib.content.resource.NamespaceContext; +import org.xbib.content.xml.XmlNamespaceContext; import org.xbib.content.xml.util.ToQName; import java.io.IOException; @@ -39,12 +40,12 @@ public class JsonXmlStreamer { private QName root; - private XmlNamespaceContext context; + private NamespaceContext context; - private Deque elements; + private final Deque elements; public JsonXmlStreamer() { - context = XmlNamespaceContext.newDefaultInstance(); + context = XmlNamespaceContext.newInstance(); root = new QName("root"); eventFactory = XMLEventFactory.newInstance(); outputFactory = XMLOutputFactory.newInstance(); @@ -58,7 +59,7 @@ public class JsonXmlStreamer { return this; } - public JsonXmlStreamer context(XmlNamespaceContext context) { + public JsonXmlStreamer context(NamespaceContext context) { this.context = context; return this; } diff --git a/content-xml/src/main/java/org/xbib/content/xml/stream/AbstractXMLEvent.java b/content-xml/src/main/java/org/xbib/content/xml/stream/AbstractXMLEvent.java index 01d5fcf..c41731a 100644 --- a/content-xml/src/main/java/org/xbib/content/xml/stream/AbstractXMLEvent.java +++ b/content-xml/src/main/java/org/xbib/content/xml/stream/AbstractXMLEvent.java @@ -1,8 +1,6 @@ package org.xbib.content.xml.stream; import java.io.StringWriter; -import java.util.logging.Level; -import java.util.logging.Logger; import javax.xml.namespace.QName; import javax.xml.stream.Location; @@ -17,8 +15,6 @@ import javax.xml.stream.events.XMLEvent; */ public abstract class AbstractXMLEvent implements XMLEvent { - private static final Logger logger = Logger.getLogger(AbstractXMLEvent.class.getName()); - /** * The event location. */ @@ -115,7 +111,7 @@ public abstract class AbstractXMLEvent implements XMLEvent { try { this.writeAsEncodedUnicode(writer); } catch (XMLStreamException e) { - logger.log(Level.WARNING, e.getMessage(), e); + // ignore } return writer.toString(); } diff --git a/content-xml/src/main/java/org/xbib/content/xml/stream/IndentingXMLEventWriter.java b/content-xml/src/main/java/org/xbib/content/xml/stream/IndentingXMLEventWriter.java index 7f52d55..9f13cfb 100644 --- a/content-xml/src/main/java/org/xbib/content/xml/stream/IndentingXMLEventWriter.java +++ b/content-xml/src/main/java/org/xbib/content/xml/stream/IndentingXMLEventWriter.java @@ -3,8 +3,6 @@ package org.xbib.content.xml.stream; import java.io.IOException; import java.io.Writer; import java.util.Arrays; -import java.util.logging.Level; -import java.util.logging.Logger; import java.util.regex.Pattern; import javax.xml.stream.XMLEventWriter; @@ -42,8 +40,6 @@ import javax.xml.stream.events.XMLEvent; */ public class IndentingXMLEventWriter extends EventWriterDelegate implements Indentation { - private static final Logger logger = Logger.getLogger(IndentingXMLEventWriter.class.getName()); - private static final int WROTE_MARKUP = 1; private static final int WROTE_DATA = 2; /** @@ -153,7 +149,7 @@ public class IndentingXMLEventWriter extends EventWriterDelegate implements Inde try { newLineEvent.write(out, depth - 1); } catch (Exception e) { - logger.log(Level.FINE, e.getMessage(), e); + // swallow } } } diff --git a/content-xml/src/main/java/org/xbib/content/xml/stream/IndentingXMLStreamWriter.java b/content-xml/src/main/java/org/xbib/content/xml/stream/IndentingXMLStreamWriter.java index 12f1a91..8264acb 100644 --- a/content-xml/src/main/java/org/xbib/content/xml/stream/IndentingXMLStreamWriter.java +++ b/content-xml/src/main/java/org/xbib/content/xml/stream/IndentingXMLStreamWriter.java @@ -1,8 +1,5 @@ package org.xbib.content.xml.stream; -import java.util.logging.Level; -import java.util.logging.Logger; - import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamWriter; @@ -35,8 +32,6 @@ import javax.xml.stream.XMLStreamWriter; */ public class IndentingXMLStreamWriter extends StreamWriterDelegate implements Indentation { - private static final Logger logger = Logger.getLogger(IndentingXMLStreamWriter.class.getName()); - private static final int WROTE_MARKUP = 1; private static final int WROTE_DATA = 2; /** @@ -254,7 +249,7 @@ public class IndentingXMLStreamWriter extends StreamWriterDelegate implements In try { writeNewLine(depth - 1); } catch (XMLStreamException e) { - logger.log(Level.FINE, e.getMessage(), e); + // swallow } } } @@ -270,7 +265,7 @@ public class IndentingXMLStreamWriter extends StreamWriterDelegate implements In try { writeNewLine(0); } catch (XMLStreamException e) { - logger.log(Level.FINE, e.getMessage(), e); + // swallow } } stack[depth] = 0; // start fresh diff --git a/content-xml/src/main/java/org/xbib/content/xml/stream/StaxEventXMLReader.java b/content-xml/src/main/java/org/xbib/content/xml/stream/StaxEventXMLReader.java index 2f5f598..319cc4f 100644 --- a/content-xml/src/main/java/org/xbib/content/xml/stream/StaxEventXMLReader.java +++ b/content-xml/src/main/java/org/xbib/content/xml/stream/StaxEventXMLReader.java @@ -5,8 +5,6 @@ import org.xml.sax.SAXException; import org.xml.sax.helpers.AttributesImpl; import java.util.Iterator; -import java.util.logging.Level; -import java.util.logging.Logger; import javax.xml.namespace.QName; import javax.xml.stream.XMLEventReader; @@ -32,8 +30,6 @@ import javax.xml.stream.events.XMLEvent; */ public class StaxEventXMLReader extends AbstractStaxXMLReader { - private static final Logger logger = Logger.getLogger(StaxEventXMLReader.class.getName()); - private final XMLEventReader reader; /** @@ -52,7 +48,6 @@ public class StaxEventXMLReader extends AbstractStaxXMLReader { throw new IllegalStateException("XMLEventReader not at start of document or element"); } } catch (XMLStreamException ex) { - logger.log(Level.FINE, ex.getMessage(), ex); throw new IllegalStateException("Could not read first element: " + ex.getMessage()); } this.reader = reader; diff --git a/content-xml/src/main/java/org/xbib/content/xml/transform/StylesheetErrorListener.java b/content-xml/src/main/java/org/xbib/content/xml/transform/DefaultStylesheetErrorListener.java similarity index 59% rename from content-xml/src/main/java/org/xbib/content/xml/transform/StylesheetErrorListener.java rename to content-xml/src/main/java/org/xbib/content/xml/transform/DefaultStylesheetErrorListener.java index 4a103b5..9cbe665 100644 --- a/content-xml/src/main/java/org/xbib/content/xml/transform/StylesheetErrorListener.java +++ b/content-xml/src/main/java/org/xbib/content/xml/transform/DefaultStylesheetErrorListener.java @@ -1,26 +1,21 @@ package org.xbib.content.xml.transform; -import java.util.logging.Level; -import java.util.logging.Logger; - import javax.xml.transform.ErrorListener; import javax.xml.transform.TransformerException; /** * An {@link javax.xml.transform.ErrorListener} that reacts to errors when parsing (compiling) the stylesheet. */ -public final class StylesheetErrorListener implements ErrorListener { - - private static final Logger logger = Logger.getLogger(StylesheetErrorListener.class.getName()); +public class DefaultStylesheetErrorListener implements ErrorListener { @Override public void warning(TransformerException e) throws TransformerException { - logger.log(Level.WARNING, "warning (recoverable): " + e.getMessage(), e); + //logger.log(Level.WARNING, "warning (recoverable): " + e.getMessage(), e); } @Override public void error(TransformerException e) throws TransformerException { - logger.log(Level.WARNING, "error (recoverable): " + e.getMessage(), e); + //logger.log(Level.WARNING, "error (recoverable): " + e.getMessage(), e); } /** @@ -28,7 +23,7 @@ public final class StylesheetErrorListener implements ErrorListener { */ @Override public void fatalError(TransformerException e) throws TransformerException { - logger.log(Level.WARNING, "fatal error: " + e.getMessage(), e); + //logger.log(Level.WARNING, "fatal error: " + e.getMessage(), e); throw e; } } diff --git a/content-xml/src/main/java/org/xbib/content/xml/transform/StylesheetPool.java b/content-xml/src/main/java/org/xbib/content/xml/transform/StylesheetPool.java index fe324af..9b9d622 100644 --- a/content-xml/src/main/java/org/xbib/content/xml/transform/StylesheetPool.java +++ b/content-xml/src/main/java/org/xbib/content/xml/transform/StylesheetPool.java @@ -3,8 +3,6 @@ package org.xbib.content.xml.transform; import java.text.MessageFormat; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -import java.util.logging.Level; -import java.util.logging.Logger; import javax.xml.transform.Source; import javax.xml.transform.Templates; @@ -18,8 +16,6 @@ import javax.xml.transform.stream.StreamSource; */ public final class StylesheetPool { - private static final Logger logger = Logger.getLogger(StylesheetPool.class.getName()); - /** * A map of precompiled stylesheets ({@link javax.xml.transform.Templates} objects). */ @@ -61,8 +57,6 @@ public final class StylesheetPool { String systemId = source.getSystemId(); Templates template = stylesheets.get(systemId); if (template == null) { - logger.log(Level.FINE, MessageFormat.format("new source={0} {1}", - source.getSystemId(), source.getClass().getName())); template = transformerFactory.newTemplates(source); stylesheets.put(systemId, template); } diff --git a/content-xml/src/main/java/org/xbib/content/xml/transform/StylesheetTransformer.java b/content-xml/src/main/java/org/xbib/content/xml/transform/StylesheetTransformer.java index b809be3..4ae867e 100644 --- a/content-xml/src/main/java/org/xbib/content/xml/transform/StylesheetTransformer.java +++ b/content-xml/src/main/java/org/xbib/content/xml/transform/StylesheetTransformer.java @@ -51,7 +51,7 @@ public class StylesheetTransformer implements Closeable { if (transformerFactory == null) { transformerFactory = (SAXTransformerFactory) TransformerFactory.newInstance(); } - transformerFactory.setErrorListener(new StylesheetErrorListener()); + transformerFactory.setErrorListener(new DefaultStylesheetErrorListener()); setResolver(path == null ? new TransformerURIResolver() : new TransformerURIResolver(path)); return this; } diff --git a/content-xml/src/main/java/org/xbib/content/xml/transform/TransformerErrorListener.java b/content-xml/src/main/java/org/xbib/content/xml/transform/TransformerErrorListener.java index af96912..d641d0a 100644 --- a/content-xml/src/main/java/org/xbib/content/xml/transform/TransformerErrorListener.java +++ b/content-xml/src/main/java/org/xbib/content/xml/transform/TransformerErrorListener.java @@ -1,8 +1,5 @@ package org.xbib.content.xml.transform; -import java.util.logging.Level; -import java.util.logging.Logger; - import javax.xml.transform.ErrorListener; import javax.xml.transform.TransformerException; @@ -12,8 +9,6 @@ import javax.xml.transform.TransformerException; */ public final class TransformerErrorListener implements ErrorListener { - private static final Logger logger = Logger.getLogger(TransformerErrorListener.class.getName()); - /** * We store the exception internally as a workaround to xalan, which reports * {@link javax.xml.transform.TransformerException} as {@link RuntimeException} (wrapped). @@ -25,7 +20,7 @@ public final class TransformerErrorListener implements ErrorListener { */ @Override public void warning(TransformerException e) throws TransformerException { - logger.log(Level.WARNING, "Warning (recoverable): " + e.getMessage(), e); + //logger.log(Level.WARNING, "Warning (recoverable): " + e.getMessage(), e); } /* @@ -33,7 +28,7 @@ public final class TransformerErrorListener implements ErrorListener { */ @Override public void error(TransformerException e) throws TransformerException { - logger.log(Level.WARNING, "Error (recoverable): " + e.getMessage(), e); + //logger.log(Level.WARNING, "Error (recoverable): " + e.getMessage(), e); } /** @@ -41,7 +36,7 @@ public final class TransformerErrorListener implements ErrorListener { */ @Override public void fatalError(TransformerException e) throws TransformerException { - logger.log(Level.SEVERE, "Fatal error: " + e.getMessage(), e); + //logger.log(Level.SEVERE, "Fatal error: " + e.getMessage(), e); this.exception = e; throw e; } diff --git a/content-xml/src/main/java/org/xbib/content/xml/transform/TransformerURIResolver.java b/content-xml/src/main/java/org/xbib/content/xml/transform/TransformerURIResolver.java index 477b3f9..947ceb5 100644 --- a/content-xml/src/main/java/org/xbib/content/xml/transform/TransformerURIResolver.java +++ b/content-xml/src/main/java/org/xbib/content/xml/transform/TransformerURIResolver.java @@ -14,8 +14,6 @@ import java.net.URL; import java.util.Arrays; import java.util.LinkedList; import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParser; @@ -30,8 +28,6 @@ import javax.xml.transform.sax.SAXSource; */ public class TransformerURIResolver implements URIResolver, Closeable { - private static final Logger logger = Logger.getLogger(TransformerURIResolver.class.getName()); - private List inputStreams = new LinkedList<>(); private List bases = new LinkedList<>(); @@ -78,7 +74,7 @@ public class TransformerURIResolver implements URIResolver, Closeable { try { in = url.openStream(); } catch (IOException e) { - logger.log(Level.WARNING, "error while opening stream", e); + // ignore } } if (in == null) { diff --git a/content-xml/src/main/java/org/xbib/content/xml/util/ToQName.java b/content-xml/src/main/java/org/xbib/content/xml/util/ToQName.java index 1b8eb8b..b84d27b 100644 --- a/content-xml/src/main/java/org/xbib/content/xml/util/ToQName.java +++ b/content-xml/src/main/java/org/xbib/content/xml/util/ToQName.java @@ -1,6 +1,6 @@ package org.xbib.content.xml.util; -import javax.xml.namespace.NamespaceContext; +import org.xbib.content.resource.NamespaceContext; import javax.xml.namespace.QName; /** diff --git a/content-xml/src/test/java/org/xbib/content/xml/XContentXmlBuilderTest.java b/content-xml/src/test/java/org/xbib/content/xml/XContentXmlBuilderTest.java index a052a55..fe4420c 100644 --- a/content-xml/src/test/java/org/xbib/content/xml/XContentXmlBuilderTest.java +++ b/content-xml/src/test/java/org/xbib/content/xml/XContentXmlBuilderTest.java @@ -1,10 +1,9 @@ package org.xbib.content.xml; -import org.junit.Assert; -import org.junit.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.Test; import org.xbib.content.XContentBuilder; import org.xbib.content.XContentHelper; -import org.xbib.content.resource.XmlNamespaceContext; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; @@ -15,7 +14,7 @@ import javax.xml.namespace.QName; /** * */ -public class XContentXmlBuilderTest extends Assert { +public class XContentXmlBuilderTest { @Test public void testConstructorForServiceLoader() { @@ -124,7 +123,7 @@ public class XContentXmlBuilderTest extends Assert { @Test public void testParseJson() throws Exception { - XmlNamespaceContext context = XmlNamespaceContext.newDefaultInstance(); + XmlNamespaceContext context = XmlNamespaceContext.newInstance(); context.addNamespace("bib", "info:srw/cql-context-set/1/bib-v1/"); context.addNamespace("xbib", "http://xbib.org/"); context.addNamespace("abc", "http://localhost/"); diff --git a/content-xml/src/test/java/org/xbib/content/xml/XmlNamespaceContextTest.java b/content-xml/src/test/java/org/xbib/content/xml/XmlNamespaceContextTest.java index c96966f..dc37b6f 100644 --- a/content-xml/src/test/java/org/xbib/content/xml/XmlNamespaceContextTest.java +++ b/content-xml/src/test/java/org/xbib/content/xml/XmlNamespaceContextTest.java @@ -1,10 +1,10 @@ package org.xbib.content.xml; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import org.junit.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.Test; import org.xbib.content.XContentBuilder; -import org.xbib.content.resource.XmlNamespaceContext; +import org.xbib.content.xml.transform.StylesheetTransformer; +import java.util.Locale; import javax.xml.namespace.QName; /** @@ -15,14 +15,14 @@ public class XmlNamespaceContextTest { @Test public void testDefaultNamespace() { XmlNamespaceContext context = XmlNamespaceContext.newInstance(); - assertTrue(context.getNamespaces().size() == 0); - context = XmlNamespaceContext.newDefaultInstance(); - assertTrue(context.getNamespaces().size() > 0); + assertEquals(0, context.getNamespaces().size()); } @Test public void testDefaultNamespaces() throws Exception { - XmlNamespaceContext context = XmlNamespaceContext.newDefaultInstance(); + XmlNamespaceContext context = + XmlNamespaceContext.newInstance("org/xbib/content/resource/namespace", + Locale.getDefault(), StylesheetTransformer.class.getClassLoader()); XmlXParams params = new XmlXParams(context); XContentBuilder builder = XmlXContent.contentBuilder(params); builder.startObject() diff --git a/content-xml/src/test/java/org/xbib/content/xml/json/Json2XmlTest.java b/content-xml/src/test/java/org/xbib/content/xml/json/Json2XmlTest.java index 50d99be..e9a1d6b 100644 --- a/content-xml/src/test/java/org/xbib/content/xml/json/Json2XmlTest.java +++ b/content-xml/src/test/java/org/xbib/content/xml/json/Json2XmlTest.java @@ -1,7 +1,7 @@ package org.xbib.content.xml.json; -import org.junit.Test; -import org.xbib.content.resource.XmlNamespaceContext; +import org.junit.jupiter.api.Test; +import org.xbib.content.xml.XmlNamespaceContext; import org.xml.sax.InputSource; import java.io.File; import java.io.FileOutputStream; @@ -12,6 +12,7 @@ import java.io.OutputStreamWriter; import java.io.Reader; import java.io.Writer; import java.nio.charset.StandardCharsets; +import java.util.Locale; import javax.xml.namespace.QName; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; @@ -70,7 +71,7 @@ public class Json2XmlTest { private Writer getOutput(String path) throws IOException { File file = File.createTempFile(path, ".dat"); - return new OutputStreamWriter(new FileOutputStream(file), "UTF-8"); + return new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8); } private QName root() { @@ -78,12 +79,14 @@ public class Json2XmlTest { } private XmlNamespaceContext context() { - XmlNamespaceContext nsContext = XmlNamespaceContext.newDefaultInstance(); - nsContext.addNamespace("bib", "info:srw/cql-context-set/1/bib-v1/"); - nsContext.addNamespace("xbib", "http://xbib.org/"); - nsContext.addNamespace("abc", "http://localhost/"); - nsContext.addNamespace("lia", "http://xbib.org/namespaces/lia/"); - return nsContext; + XmlNamespaceContext context = + XmlNamespaceContext.newInstance("org/xbib/content/resource/namespace", + Locale.getDefault(), Json2XmlTest.class.getClassLoader()); + context.addNamespace("bib", "info:srw/cql-context-set/1/bib-v1/"); + context.addNamespace("xbib", "http://xbib.org/"); + context.addNamespace("abc", "http://localhost/"); + context.addNamespace("lia", "http://xbib.org/namespaces/lia/"); + return context; } } diff --git a/content-xml/src/test/java/org/xbib/content/xml/json/StylesheetTransformerTest.java b/content-xml/src/test/java/org/xbib/content/xml/json/StylesheetTransformerTest.java index ac47637..6942179 100644 --- a/content-xml/src/test/java/org/xbib/content/xml/json/StylesheetTransformerTest.java +++ b/content-xml/src/test/java/org/xbib/content/xml/json/StylesheetTransformerTest.java @@ -1,13 +1,14 @@ package org.xbib.content.xml.json; -import org.junit.Test; -import org.xbib.content.resource.XmlNamespaceContext; +import org.junit.jupiter.api.Test; +import org.xbib.content.xml.XmlNamespaceContext; import org.xbib.content.xml.transform.StylesheetTransformer; import org.xml.sax.InputSource; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; +import java.util.Locale; import javax.xml.namespace.QName; import javax.xml.transform.sax.SAXSource; @@ -18,7 +19,9 @@ public class StylesheetTransformerTest { private final QName root = new QName("http://example.org", "result", "ex"); - private final XmlNamespaceContext context = XmlNamespaceContext.newDefaultInstance(); + private final XmlNamespaceContext context = + XmlNamespaceContext.newInstance("org/xbib/content/resource/namespace", + Locale.getDefault(), StylesheetTransformer.class.getClassLoader()); @Test public void testJsonAsXML() throws Exception { diff --git a/content-xml/src/test/java/org/xbib/content/xml/util/SaxEventConsumerTest.java b/content-xml/src/test/java/org/xbib/content/xml/util/SaxEventConsumerTest.java index 69eaf1c..d64a36c 100644 --- a/content-xml/src/test/java/org/xbib/content/xml/util/SaxEventConsumerTest.java +++ b/content-xml/src/test/java/org/xbib/content/xml/util/SaxEventConsumerTest.java @@ -1,6 +1,6 @@ package org.xbib.content.xml.util; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.xbib.content.xml.stream.SaxEventConsumer; import org.xml.sax.helpers.DefaultHandler; import java.util.LinkedList; diff --git a/content-xml/src/test/java/org/xbib/content/xml/util/XMLUtilTest.java b/content-xml/src/test/java/org/xbib/content/xml/util/XMLUtilTest.java index 84ba2be..45206a0 100644 --- a/content-xml/src/test/java/org/xbib/content/xml/util/XMLUtilTest.java +++ b/content-xml/src/test/java/org/xbib/content/xml/util/XMLUtilTest.java @@ -1,12 +1,12 @@ package org.xbib.content.xml.util; -import org.junit.Assert; -import org.junit.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.Test; /** * */ -public class XMLUtilTest extends Assert { +public class XMLUtilTest { @Test public void testWhitespaceCleaner() { diff --git a/content-yaml/build.gradle b/content-yaml/build.gradle index 4daf6d8..3bc02b3 100644 --- a/content-yaml/build.gradle +++ b/content-yaml/build.gradle @@ -1,4 +1,4 @@ dependencies { - compile project(':content-core') - compile "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:${project.property('jackson.version')}" -} \ No newline at end of file + api project(':content-core') + api "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:${project.property('jackson.version')}" +} diff --git a/content-yaml/src/main/java/module-info.java b/content-yaml/src/main/java/module-info.java new file mode 100644 index 0000000..e8dcf14 --- /dev/null +++ b/content-yaml/src/main/java/module-info.java @@ -0,0 +1,9 @@ +module org.xbib.content.yaml { + exports org.xbib.content.yaml; + requires org.xbib.content.core; + requires com.fasterxml.jackson.dataformat.yaml; + provides org.xbib.content.XContent with + org.xbib.content.yaml.YamlXContent; + provides org.xbib.content.settings.SettingsLoader with + org.xbib.content.yaml.YamlSettingsLoader; +} diff --git a/gradle.properties b/gradle.properties index a06606b..a86e661 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,17 +1,12 @@ group = org.xbib name = content -version = 2.1.0 +version = 2.2.0 -xbib-net.version = 2.0.3 +gradle.wrapper.version = 6.4.1 +xbib.net.version = 2.0.4 jackson.version = 2.9.10 -jackson-databind.version = 2.9.10.1 -woodstox.version = 6.0.2 - -# test -junit.version = 5.6.2 -junit4.version = 4.13 -hamcrest.version = 2.2 +jackson.databind.version = 2.9.10.1 +woodstox.version = 6.2.1 mockito.version = 3.1.0 - -# doc +junit4.version = 4.13 asciidoclet.version = 1.5.6 diff --git a/gradle/compile/java.gradle b/gradle/compile/java.gradle new file mode 100644 index 0000000..7b1e601 --- /dev/null +++ b/gradle/compile/java.gradle @@ -0,0 +1,35 @@ + +apply plugin: 'java-library' + +java { + modularity.inferModulePath.set(true) +} + +compileJava { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 +} + +compileTestJava { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 +} + +jar { + manifest { + attributes('Implementation-Version': project.version) + } +} + +task sourcesJar(type: Jar, dependsOn: classes) { + classifier 'sources' + from sourceSets.main.allSource +} + +task javadocJar(type: Jar, dependsOn: javadoc) { + classifier 'javadoc' +} + +artifacts { + archives sourcesJar, javadocJar +} diff --git a/gradle/documentation/asciidoc.gradle b/gradle/documentation/asciidoc.gradle new file mode 100644 index 0000000..34ace12 --- /dev/null +++ b/gradle/documentation/asciidoc.gradle @@ -0,0 +1,36 @@ +apply plugin: 'org.xbib.gradle.plugin.asciidoctor' + +configurations { + asciidoclet +} + +dependencies { + asciidoclet "org.asciidoctor:asciidoclet:${project.property('asciidoclet.version')}" +} + +subprojects { + + /*javadoc { + options.docletpath = configurations.asciidoclet.files.asType(List) + options.doclet = 'org.asciidoctor.Asciidoclet' + //options.overview = "src/docs/asciidoclet/overview.adoc" + options.addStringOption "-base-dir", "${projectDir}" + options.addStringOption "-attribute", + "name=${project.name},version=${project.version},title-link=https://github.com/xbib/${project.name}" + configure(options) { + noTimestamp = true + } +}*/ + + asciidoctor { + attributes 'source-highlighter': 'coderay', + toc: 'left', + doctype: 'book', + icons: 'font', + encoding: 'utf-8', + sectlink: true, + sectanchors: true, + linkattrs: true, + imagesdir: 'img' + } +} \ No newline at end of file diff --git a/gradle/ide/idea.gradle b/gradle/ide/idea.gradle new file mode 100644 index 0000000..64e2167 --- /dev/null +++ b/gradle/ide/idea.gradle @@ -0,0 +1,13 @@ +apply plugin: 'idea' + +idea { + module { + outputDir file('build/classes/java/main') + testOutputDir file('build/classes/java/test') + } +} + +if (project.convention.findPlugin(JavaPluginConvention)) { + //sourceSets.main.output.classesDirs = file("build/classes/java/main") + //sourceSets.test.output.classesDirs = file("build/classes/java/test") +} diff --git a/gradle/publishing/publication.gradle b/gradle/publishing/publication.gradle new file mode 100644 index 0000000..c35fcb9 --- /dev/null +++ b/gradle/publishing/publication.gradle @@ -0,0 +1,64 @@ + +apply plugin: "de.marcphilipp.nexus-publish" + +publishing { + publications { + mavenJava(MavenPublication) { + from components.java + artifact sourcesJar + artifact javadocJar + pom { + name = project.name + description = rootProject.ext.description + url = rootProject.ext.url + inceptionYear = rootProject.ext.inceptionYear + packaging = 'jar' + organization { + name = 'xbib' + url = 'https://xbib.org' + } + developers { + developer { + id = 'jprante' + name = 'Jörg Prante' + email = 'joergprante@gmail.com' + url = 'https://github.com/jprante' + } + } + scm { + url = rootProject.ext.scmUrl + connection = rootProject.ext.scmConnection + developerConnection = rootProject.ext.scmDeveloperConnection + } + issueManagement { + system = rootProject.ext.issueManagementSystem + url = rootProject.ext.issueManagementUrl + } + licenses { + license { + name = rootProject.ext.licenseName + url = rootProject.ext.licenseUrl + distribution = 'repo' + } + } + } + } + } +} + +if (project.hasProperty("signing.keyId")) { + apply plugin: 'signing' + signing { + sign publishing.publications.mavenJava + } +} + +nexusPublishing { + repositories { + sonatype { + username = project.property('ossrhUsername') + password = project.property('ossrhPassword') + packageGroup = "org.xbib" + } + } +} diff --git a/gradle/publishing/sonatype.gradle b/gradle/publishing/sonatype.gradle new file mode 100644 index 0000000..e1813f3 --- /dev/null +++ b/gradle/publishing/sonatype.gradle @@ -0,0 +1,11 @@ + +if (project.hasProperty('ossrhUsername') && project.hasProperty('ossrhPassword')) { + + apply plugin: 'io.codearte.nexus-staging' + + nexusStaging { + username = project.property('ossrhUsername') + password = project.property('ossrhPassword') + packageGroup = "org.xbib" + } +} diff --git a/gradle/test/junit5.gradle b/gradle/test/junit5.gradle new file mode 100644 index 0000000..cfef972 --- /dev/null +++ b/gradle/test/junit5.gradle @@ -0,0 +1,27 @@ + +def junitVersion = project.hasProperty('junit.version')?project.property('junit.version'):'5.6.2' +def hamcrestVersion = project.hasProperty('hamcrest.version')?project.property('hamcrest.version'):'2.2' + +dependencies { + testImplementation "org.junit.jupiter:junit-jupiter-api:${junitVersion}" + testImplementation "org.junit.jupiter:junit-jupiter-params:${junitVersion}" + testImplementation "org.hamcrest:hamcrest-library:${hamcrestVersion}" + testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:${junitVersion}" +} + +test { + useJUnitPlatform() + failFast = true + testLogging { + events 'STARTED', 'PASSED', 'FAILED', 'SKIPPED' + } + afterSuite { desc, result -> + if (!desc.parent) { + println "\nTest result: ${result.resultType}" + println "Test summary: ${result.testCount} tests, " + + "${result.successfulTestCount} succeeded, " + + "${result.failedTestCount} failed, " + + "${result.skippedTestCount} skipped" + } + } +} diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 5c2d1cf016b3885f6930543d57b744ea8c220a1a..62d4c053550b91381bbd28b1afc82d634bf73a8a 100644 GIT binary patch delta 23020 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 delta 19839 zcmV)EK)}DA%mcu(1F$Or4XW8@*aHOs0O|<<04pTwK!b{dHxe$1wboX!v`W1o0WAS+MB5I@A&gFD(#gb2?-zUh2fp^DPhG2h z3AC=-)z|)u{);|o_nFB+5`wEN)|oT=?A!P4efH${GOj3?!c~8qhJQJV!76V>q7E&2j*mCWsE53!n}+H1!u7+?OJcbtmfIb8SHXLDUxwa+WwFgGID~=>&Ja0gScW^n5K1H$8Kg*^Ve#2& zX_-6o`m#xqXvWU#=A!Nx;=L}E+*PB(kj&UlF#LGeRg zu}hT8?q*|#PXF|(?ojr5+j98>chb}=m5i+yI0@svg~i?U!d#}|NEnwWYfr?mry;f{ z5~0QU40nH5?E*tzgM!0XOrCes{uycZHWT--9FP}lb$f1Tg7kM0SNXd$df8Kxu|mNv zKFIU3YuHvrMvqELhn@0`Fb}h9wO4zj*=B9|+M6&UEOpP}ed#bLP*`k>t&7PKW1?>_mayR?1 z;__1SMGQQ&T6njZyVrGxTQoD0!ORFEZDW5W21i3{%&$6JCkl4utB!CKyvLft`cjd6 zg}ak&#zkM^1>rhP+SljB@x<0)wFO`uT2P)h+t@5^u}QvY&_oRDo_&|P`fQ^w|6Vlt zs*93aMO4(hxG@YzTLwxSL>_8tTyZX@WFonxnPfsZtBdK}%=N|u?{1ZmO-Xm@ijaTD zo_0LmB%mv{LrN_`+mO}<=tktW&KK#EJV4)O@fQLUBaqf(^p>V4qi1+%4eVFi?7(qa zBc5yn2;J0lWIs%62sHbPTDogPBWca`j1S|L|=qx;t%jg8Sj*W z4KzjfVQ1#vbIv_?ZsynT?>_hmdy5+gJs-ykbrMv z#l{_m@n>Ni>gNmzKflG0EX$f;xL65efAPA#yCc*az7tWztH>&kwzvw-xgSjGM%bd< zhLU^TwYF}EScg@vrDAYj#<5W4h__mTFvW^g^`NeJEfPUT@n%z~;DzkOk>s_dvjQcC zsk+b`MDIvd8_0z+W?1y|mG}Gu4`QK%;h>U@y9^8d$ik~7)3vo%WSBb#$lz?sf3~WM z_0aU5K28;k4;N`nlEyin7$zH9Hw#VE@7tD8HtxA7AfQY9n>gk&z$A+{R$ZFz15@Oo zjYkZH|GP|v?1`~ciJ6g2Gh}+ih{yF{v)j^Qmtn%pMM*;HF2k~48GvXN#`RMEY>45> z5a2&jGpA!@Ld$Z4t2L!KnMnHif9*0uZb*skvYGJoh&C}#uf~P>60po5K`($#0j)Fx zjIA8N`brxM8Tya+f*)}SW@3IG5I2mk;8K>#(jJe$A{005jF001GAkwF%dUe*qOommNd zT*q1ef70&0r`6Np^|`*XPV89LX*-S`%ZU?9zGTaitd-=-cH%rqPtw|}UFGdt+e%79 zN)4qYgrhXg(WF4zKq=s~^~#OfCIsq0fpSxz#F$;HTyXezZt}D;kONZK8PTG zCy3w0?*;J;eqS|zpm_dJHGdSu4*ao!FBtffAeQ4#g9zczf_NTZRMTHl&7Yh2iy+>Q zzf{d%8ThjL{&f(~;ctTYTYN<|e^*6me{bR+g7`=LlYxIW@p=%O@h^UVsDJfMeQ4*CbG$tTTQvml+C7WG39ns zwwltQHrQrJqajTKt1FRk+|Ib2N;xS(sLxGao;i^ACY^*A8@0WpE2tanIo{KIs^{F$ zq5f!BZx7kJ&)XO6wz!>`Xp4GoEHSZ9P}7-Aq&z#}4cYOuV@k7spti5S_elStX!Km? zQEnoTu1e)=L3PLA;lqde&qcdVAF2czND9Q06B7>Qt?N#@6KxZ&Jr;M`F1hyfwBxpQ z>q&|+IPS5h9Qv2NA;(R{k_kcmw40o8om8qjmhzm0+NY)5J_nPR67i%x*0+G2I|uHL zC1T!wK}W+98Z0({eKBR*kigfO9HWwT-LZtzlb#xJ+yQ$e?kMLaNA38K?Z(tNNA!7< zG5UYQQYur$I2E|kp_3Y6LC+z8*HRf1Otl*Z0 z?7j)dYa8tE%1MbO+YZO#j+S89V`EA+rb{U+vt-Okd9g%)PF8K{S|-4u%cIV;n&jg8 zyv(kI=eP+wPUX^We8H~WTvnS-Iqrc8Czq)V{78CyTxCqfnGWicNKf@UO7|MtPH%bL zPGZ8FWGwSJ)|pHzAvW${u$H-I!qG0$*=i=ubK%X2>0s zO`mtzso3bkcy22juEj>Ezy(JOV}@KgwJR~6B&LkmDQEYtLy1vc0k=1l$*gh!Qa|B% z*+uRN$D2&jmurjoTxUE^X>Hj#@>`B(&hr}Cp<4=nPrW1OxkyD_(eCVZ57}-!rnpuX zaTO9N&$y?EF`y&M&g!BS8Zx`}1f#M`u#81LnvUC^Gg$D%t>pt!YPR-VLL-_v%}p;Q zU0M?=*-mGxU`0dO9fFEBJD=FCY99-i@u+GZv*03S!NYkAY1LfBB@5q=$LPLE&zo+YR$!qtH{?!BcH<+0 z)+OL+^Wt-da%7JocUiJm+AY~9cUy9g?6>ePyu-pz<7X_nSMDP~Qu`lJO@}3&a?rwu@L>xtVU8|PinnNgpIdTB4qI|Wj`Cbu!T?LUq#5>s&Drl&n;%#eOdqB0;@Ua0WiLjDQD`7I-t>{O&^VXIP>%T)aj zS~4W340($s!*be^Gjdh{OYWBeOCC^Ru!HP}`I<%A+DOj|>qn z8ObAago`3av;!k!Jc!)bNLulFFeO7>kfLL;Q#w8#+17|-TZ|wFm+)p=BD(u^E3;|OKN|A6gcPac*`0V zUo^uFQ1VwHyUfelpyHVxa#HdqpVLG6>RjyN;rtjjdL+$b> z5Z@_YIz znoN1wULQd)*RxfqO!iKu9fiZHs1CdK#FW0sO~0vJSxo8r-j*qU8v^vH9ZxL?RqlGM zs;T8o-P3bNt-7~*g~LwSsZm9_blbvP^1f`wm%vVVF_<=IF;*;$rdwL%+9-AJ3F=ZMnyYa#+WVr+#u-Rn9{74sBdI zM+(TFeWo{bE)^?(m3{NilE8Sg`_PO7*oh9#bh15&E*wT5j?m#pF~rdrjRF_ zq8}e6=f^RCS8GMzKjR(6`Z4g7N_xb(%!&X5j-G%oRccpVqrw5z>iX! zTD*dH<3||Oop=_HGjR<{zQVaDm@W^p)_;tDRh0TR{5X3-%6tSrfuBS*b-axCuvbHC zUc*n(R-a0Yd`hvGODXoUDODlWcoOeJrKq&duJDVAr)ZO3C-!@x6t z2A(zWegn@Lc-}z2ffEoP<=kYAF2yC9>l^5}NlgQb83|E0X-&xt6kQB_;3f;Me$h<+ z9~s!(q&;Q#Eh-#S{kV~<(&O}^Dz8m**fHFg!A@aw2mf~Q?@s>h=HH%K+;z23w*kH2 zLJ#T%$*j8+tk*i0tA@3T-TaS9D^=5e~?Uo(TVAG$CX3)CgW69^ALTdeqeglLwAo~euVIq6(yYD2 z%abgteiqauOX*P-(_<_o<*&1U^uQW&`~u6jlH9j3Y9FN=_LBNb_+>_Ll0MGT9%Iz6 z;zjoQ2@)S;Phs}s1z$g|{mLr{<$oNXppMGJO{lm@@s&C^Sqj%wN=I+# zgagrGvne`UA82M{v_!96V{E<(vsLgs_51+TuazN|beOtFSbbYreag0@S%q@81qjHW z(vh(kh)-+VLIi-%XxqYs`j_<$A;Kzpg*`v_*^OUeFF?*$wd7yLguX^qU|j!SO%v+> zMNT64ZL@_Sq7@2oK;iXc2LJ#G5R)-BDSub_e;j2Ue%|ac)6ImYfd-eh5T($~mSlU- z)}{w7Nh^^}T9PKAp(vBx>1LYA%sM;U0}nj#RunG?rzb^4DcEdNs(_-XhziQD{vCck z0_yY5>~1!jZEXEv-}8Gs@B4ke-*@)4f4}e|fK7O785=`3M`e?f&7^Eh*&K^uGk>NO zSTU%WR$#{v!<3vja+Fu`5!t(Pr63zmHbvPSk0FB-F`UFH75B=OkII#gsra~5`9uu& z;gfRZQ_c7^J|hM0m($NS<1jwgjB$KkHeXQjMY;T?7`}|J#Bir{mcdtL^MHb{srb5z z2UUDS#W!Q<#JA+ex23i3#CU**6n{LdU`D|s08+&;EMDy{kWbo zos^vK5NMV%S+n5vnXbTZ!6g|_iM_j9_WE);;WT>A?E2LP)v5%U$qN__efzGt! z=2AIV&ss+6gsbQChMO7-`rcYm>c{Kd3{UEtwrm|PP7AaJ&Me)|rG_bB=YOaW^(M{2 z+6@A$8+qxs3!ZLSQf{Ydo8E4L`x8qEF1&AMnYINZ02m;E4p;IcdR!_ENpP zSm~|-p4hNcbTdY9S6Vq7-BOI<-e+elr$7=67~Z6lRq&*S@8WwJcH(-)aWer!u5Ah=nPvJDf+wDwgcv{Z);Kv$% zf}d)5Mm9f_Yd^=c3V+UMcn;4CM7s03>uLCf+&+t0daVSS#yh0Nl7e#@=5Sua3%H=* zml}SB7d5lCeQhwXSBMf+Ye-$CYdcn&+!Euan=dVj&Odua6yd7?M*Hw}N6 z{%@0aw0fy5q3!yR3#?f(=9Ng4D*>zELXI+r=NI}tgLS}hD<|{))ST>^i-RMTGOnR} zeqIS|Z&j1gStFRKu(48L4De&PmTHFDs9_L@vcOJDz<2;%sncq zo)atyT%TxEMSttdVY6B2tB}Ko%bF533jxmM#JP8(;8;b^IH-G*ycj)`F$%2v8(8_% zmtD~t9Ao~jRy8m-U+ffF=tf+V)i<&5LFlZ13!_=ddt)B$Mv1m@7%ONSzLjYwm-DZ6 zK^V&QX{j*8FKUc;Y&ne1%0_`5ork~bH7e7s^Sxw#cMD2bhr75FK>V-k$B(pPY`&|XV%@RP@ zOz|DxZw#o+ZM2{fM_NKz}`)Jd36hmR&&X@HsRGGp&S{wkz0_ zu>2f9s<;{|VZ{vAtS_N$2JKuBaxvJrat>FW2{hXtff7EAaA+6j;W?}vTs?!SCH=Hl z{q%(6;S#PMlh)_(p0a3LoB~}XTtlG}Rt1}@rTKXHJl2E|4+qw+9jm~a!*xCWE}!q7 zNPj$X9`6;H!7e#^pTNsdd!lttuBVfDlxGRhlpV#Rb67ie`ads~Ek{bYp~U#mAAj6j zSKep}+$K)ro}NgZ=_E}C2&M71^}#e$p5C;;VU1dsL_~+(Re^YrZ zs;$~htG3pvpSJxL{fegl^WMy4k_-a!Blo>`mvhhZKg+%I+!qHA5z!p}$W7aMxHKcA z87a*uX+~#%qsftGjC_uDQz7RnJkCb^>SJzlbDoTim&W7f2|Q7nNp7CZQ`~d|PnE{2 z@JVhO%hP23$qG+*alV@#;28?fbkhVbaMK1^9i!0>0SlC^EB4ekzDUX-B_%wMg%jQa6?&d14 zcH^x^;T3LLh`lg&x-=`LsTB%m2!%6UTqiyC3O6Xc%EhZ)e3o>qanmwxlxD4)UgLEN zuUB}3yq@i*T5fXFNMQwcF5V;`=Snk2;mvMp3o^n&KJmnZ-~4Xy6F?XNIox;w~NIz7b*NrCbc#k)}vKH zEf&*bOrGkR6_xAi)^4t@ZCtyicKN!swW}I`Hm|N+yOJrV?mTUqRvy&Ct>ukIG!SlG z%rv|z5{?;K*jTRx*E89xB7U7|WL+SvH^f8DdUUOZ zL9sx@rv=w*(SUp>I_*YV0G6ASac8kjFbMA5zNoGldUYUXFfGa`!3OIIgSG@(<5A5B zM8b;;Eu#k_<)RZYg)e=asqnZ-K_WkYwvPsyO8e|$_kq_%e`MNc=n39`5rLj$$ zGk-y2Jj66QD56)V4J!OCbk_~;W}0_QEl(e^3Og&Zb9Eq^Vya(e)!h7?K)ZZHm%xeM zF3VyH?|@k_=!*xT-ZX}%6%3?On8|x=ZF(mY2k=)5OSYKgvqEr*$=39k?u$o%14dVQ zJ+KHMRtH-3m?0}$#OS%HJ!-@4aRYR9Erd~q8l27XmKK3}*2d-Vw&pHaUo$kOY;0|qV`?ki!Zu1LnZ^vAAS3z!gs)1u-Qtv$%@ws_Y#EKWL$&Es+*Sx!83}>TaOD5n?*4$&$Iz}Mrr!`M#m7WN#bNUz0m&Iot z$Kn$WqFJ4D`*&G?AiFF+VRNUuO_J2Y6P8vMH=42Ag1(xVS0>X`dYYb5=^c7krCxei zrQg#ZRC=7AQ0Wr-mP!}XH&uF&9#ZLYz6u+kP^l@4zNgZ+=`xje5VG#~RsI2At@1T| zt-{yI$Mq`zkZ(}=M|=a)@zI5vK3j^wBg& z1qH~;xA3hh-^RDAdKq`Ck61H20~zo3B;*XY>YgLI27% z@vspH>8Y5_wB>YD4sUur;GLNto9XpO^q4msF}x^04J{D%YT+(Siz1;$B$}0ZYZBSj zYec*)2;^RWy%UKz*yWv_n%7l^QlfwVRn6z2Tjihg{i3G_RNlk)Fl{<26N$ZJ*dpQ$ zeKihL-pdcFbSvGa@n{_?xHMCH>q-}3Uz-TMW51R#fG~_kfGy{!)?wy&j+@9%ek4CW2=<-6-U9y)2 zu+jv;$`a!c+bcz@HxPqzq9P*<{3+K;Q`4{jIP@wZ>F_j(;VD4oma= z0HIRlnaVHlwaD+HLV^E_$!P=2ER|o9X;Z#`ywXzmWtD%;uc-X01iQSUks+aiqN+$d z=r^4hwJ4k;S&Vwy`>RoJOC(z1m8kI>g@3E^Yy1Eb@#>(i#RN`XIqZt-!M1R$K#K{r z4lQhm)5S4IV3u%Lk2{)5VYukqDbv_Y_2K}2*S1A}BOTTm5cRth%>}i!@|<~`HxytIN85q=7*$X> z_=;luph;rakNMtXS%PWviCoEirTdMXL2R3+nUr|_MsZ_a>Z)VMS1!K>YVEj% z%Ul;awZ!?VGUG|fL<^EL;E7|GQC;;8#{W5xB3^lJHhZ&KT{WmeW1+^Km2I*e;F=TMUssWhtkBem>%SY!H>?c5*_u4(68QRyM~X!MLG|D-2AyU8pkP zoi^mI^c#iM;HLjvJSIao)X^?qLAi?3I|HUcEd%4rjI!Bsk0V$#FH#DJ#JFLBSaq`a z0}GlTwmbRQS7g{?6lAK>!jUk_!k{J8xPlB93TCJSoTH{D(-ql&m7;WiXaNKHA7R-< ze_901OA7%5ZxP35KDo<&WBP{@S3=V362GW3?|qh>5N3wl9!U_YPhO~{nG!MHbiLsT zS5JNq47^tFV!6{v7A)rR@3>qdc`xNT>hWIgB_gd>AX%L#l$mB67yZRaaje8BaawN4 z)-|SnUr8HSYzB$CNC%>SB378L5t{Gx(-y_G>@)_er;G=L_egR zkZdC4ype9gtZ6ifevCIK-Hg?Cth@zlaQwC8;S12`#>l0AIpg<}r@ogaG!^&I#0J{} z`{+^hu&ct6YtOosCY5>|-85-|J=cCq-zOy=hb&yseqJIn|jDwq1YC< za$O$hp*v{SXzKGgb6s;U+)pP}WP7r^X`1~u8sDLY0uyR9m6~ZL`JgC2okFcpM}SVJ^Jooi#f%`nLUcYw zs0)1;QPfmn3j~zaw?j$UbOz0*JLo6m5}{LSy_D{RlHeLxbr;5k5FNgt)y{3 z!6Awt#b^n_$*qau(!s;F15}np3C!8kFxP>$6JmA&=U)fnE}$xSXuoeXq?FTOVu{VS zeNbY57FMpLZt8(@_M=xd6(>Ch&?9QdrmQ10U7>?h28h^84<|%?2|5%eYD%A`s-lt} zDzC7Yir>t-k>&zYvp3|-QA|mS8=LItnA_OoC~a(Vdh8-ug<~(x6GYCp@23TOQm`p9 zv3vkOx@ZY(3o&w)l2EVC)hM!z%dXp1z~9sKj1{J{hGU~_^dAQ7PDKpb(@S|x#W_oR=(Kun=%r;%&PS-S$(FMm z2Ff(WI7D^xv<+BdY)c@u`B3IdeQW%D=_zE`ZfBlhgn~y zS4=n`P66OBFev~SgPnh4!Z{az{QNcr=NfXk`mnDnX?gswRA`w(uPL-rp?abtGzEQq zl9$sb5iM7!@eGC54KD=Q*XfN!25-Zcc+G^IE&EB^OU>Qnt1Hg&caxrVCpql9ZM#z* zoMW>4Bv^ln#sOmE0WeXbp)h?T}8F z`Q~vwx(7mTLYj?&yC@mv(+!|Y1$P;$x64urYyj8@mT^Nhqo4|Z50o*T-iGqtp;IC0 zGI|e`-UqD@kh(tvr4NvmK14?P2=qQiEdK=5K8E5xLG|+wQ`u{vm+5pi{e}Jtjcr0< z@E-jQ79WMY_CEa`J40tFWnTk|RtCEUbOrQREP#-Mk7_<^wBr`=L*!U;?E0HN~ zMxVenf3zKCS3_|r%B`ja_M2!#NvT2*B(@sM^+_@vL0_-)R32@%~d(d;dno zi{wk6r$7m!DNW>K?mea^^67t|G0Ejq&7#Hz$mY@inuX4P{ics0ha>*)JwmzM&-5r4 zcKS5IbPZOCrj?>%0Z>Z=1d}e=8nbm) zoB|DRZW$4_0RRAC0{{RxlL1>Jlf&5#65H4Rn%86N+c0z#vKz0e2(%4H+bR(O+m%yxmJE*!Xg zuSDA;P;?6?+8Ln`?T+AHbKb$Cond+uPwFx16w63Z=1erkVu=r|XE?}uP=?j9p3z}g zSMg-R8uM+siqQ=USAS_do78r6Fm9NPCOmx*?A`}oJ^*&`%-ZLy8?2DH@|xd7e*jQR z0|W{H00;;G002P%9ZJ~Z76$+TTa*1-FMnxc8&?%QV@n!Y9>j zK->nrHBoEX!CP_C)*V|Dc@lY~jz){g;JbqVVi?~G z>MHMe8I67Te)AN&N$+6AVvVUV1ECpKHvJ877ua`G1`%v{;lMR#=YZBYl_5^#yx+FmOP8k%Vcs35$mmy8)*0vXQItS7eG zg#z8My_G6|aOF!^%%XzX_Xswb*>rVWfkGd<_E??TTr-M(d_pA`f(Y}DzIG#{ z7yUwMw~dX$O=D`)F|3js_JHL^OJQ`BG-K#jf)~Sn-xJGlQj2rxLw`ab;a#-zwW8kD zrtu=nK*bLfL}+)MNplm@e|UiE7a|}z=E3PsrN+%% z+H#DXQ2LW7jAC2pyr$q-gUl=FsqfB}Eyvt2_Wap9Q7GrLF{|Lj)>)`A(<+vom{%$z zV*Af@m%?B0x`sQbXsC+2cLXl>cJ3L9j=D3mtJjS+XW!PmU*h+_!~4s_@xg-ydh9^s8+U82 zGv2V!4=RiQBri}_R>AN)y7qpFNfUDlyFQ#g(32Y&TJr7?+nC4EUw9nG8g}dboxc&n z-Zwzo8yW>C|9?*_^4dh&ee%}G<;>xpAKJ^p(h$6M7Kjf@LkpFQS>2(zVEpR1FbZXT zv`{?l?R3S{4KtHy)Yt1f3+r~_mNY=u(N;e4B%d`lXRnFL2Hfd?OR2oN+eMGZ(~WVZ z=lfM)JYClFr33c7vK<|~vcGb-N{+GN1@W?7V5*$0Lw|@Y;S|4;&hm?_8QpjQ=b+$& zTs2{k>ksW&C;4L&q#WiRdm_h&xOzWlg>x`bh4PxKdVynvGth?s?!`waX`T{3iZRY& zVB9zGFf~OtA_fx4J7}s~IYL_CcU6EiThQ-XI__!vmP8U-LSh1wzRmvB6L2m19e&c3RlsxgUE6ftz2mpv_+3_=ninGpuLKY^TA!+qx*ED z`*dAtsD3E4gJa8y?qGMQiq7qtJ3R<-jMJ4tv?GBNjOql2u!&*UwM!o9nrpW)#qh9J z@C+_87fn2MlUnB(mJ_h}`kZ5ECK$>`7=j?}w144IN+D|UW%7ej7#9iEz zAz=5+5Yc*eaB?|7M!i+^bqrK+?{;PfvE}F~W~%>9*YYW*{5`Z+kKGu@akSFs4ko*w z$bYAaE&M(}|3m1-WqgeIt&Gnc=6UusCEpW1?z228HhUPS`!Yk4nty={eFPuc9_kA`Rl)sr^yBmx^f5^PGRiO(Ve!KW|UZ5EX++;F3SV7_? zgcGl$X*(HBx~mSk8_}V=7_MSuTe9buRW!wNa%<~-yO-k3n+J$LPS7Vv;z_1zg(5|y z@44NRHR6-V))GZ7N4ogG;TGvNrd-OD?jAshFa^jR*WQn8QQaknNQ?Rd8MExl!BHR zGuGE-eI={u>YQvARda~6hc#WZMi?eK-PQlqu-PkRdP7}{48AdAMP+CdjM>fgWz~Ex zFBgat&KinbSd>jooJ&lfaF^j?=9Q(IJ5Ftl1(eOVQGfWF~-p3(2gk*T7>noGrKCkkrM@3&nFfvQ`7T9 zm7Fej&nvLW2d`}AMdB*(=*tquTCT)9>DxOxB0#dDtj)+9_NU-@!mxHORp1_L z%B~d8+oV`hVo5VZs=3D?Ef|}oqK<2#d|E1WdPJ^&f(YY65Fs>iJPl$T6C9I4OyLqo4;wr8Q$7ZOIT@6eh1K)C-pu5Tfa|(!BtNbY3niWfq zq3=vRR!vNf#mts$s)u7bPLMu*(@^cZSJ8<@;3!d@$%>*Di;;mORcUV(jnU<_>87O> z64X_HqQed`sGakw#n4ecF>=eRs$%WkEoX7e(cC%|+PkA>%{jDV`OvAhd8ezId)1=- zI>X>Oxx!CUFO9(emAd$8P|-%e{6=~luuw=0G@`uli1`NkZPICy&R*Js(by+=qOtf6 zydUW7K{KrlLdGUg!zK}6Q)nSx3&}_ymv9Atuqm2M#ACQl)*RIL@WV%YCi)Sc&+x^+ zpvHsmsGaTpf$%Q)Qj8@2DBD5Z_AaC)p|^{`QY=oaVE3M|e%p3fxDpnCYz9qi7R@Y& z2%ERvi8_Y%-O1n<+Q|(;-6qOIK_?Nx9m44#t{?0-A{@0Lf!SGdI7d=}!|e>PgACM5 z3Me*SW{U5d;^-o9W>Zl+2ZD+rZs)k$#^}Li+DFN313kuCiF1SYn?4D51w_bCH&W<_ zc!i}fMDhUb4&6MBn6sVad28Ev?jgDLU9#rIU~zWUZIcBw@7E&At}?O|2osR z=-<9WJ3T8oU}A$zCNuq`-97v1oNqs!Jvx8>`|Aq;b9f+Q2#Y7^k&zL>B1cY!ge4hS zTn^$2u5x@N7Rwwf0``Bg3>nurt_N^~W6owHmsWBlMDC8uk^28sva*DPdS|*2=ndS1nh`63*8(wYs5NhFG_ZlAy~FS-hKCdy!mt1UbD{r_BY@B zIQz_;)lqd(K-?}?XXExQE^~<&eEyN?(QE^LRT00juzF)_Vviaw=W-%Ek!0gRYoHho z^)X}=J=@ZnziD??fWfUtl;|gpium$Y+fO?uC;TifvKWes!Y;R;g)Rx?cEsIr%>B?f zkgSnjOlJi1sIIE_p?FNjUE+d1m(FUpy1Wc9AiH|!{Or4y@fz#7RrbvU-JzqKXuwxe*`Tb zDB`x1%yz(k1|C*wb2+4zJ`5EB zZTkMuy>U9P-P6BBmcOSSDt9|XQ5ImcKp#Yxlv(@b%!O#0o;+{gLL+%oU6T>Ky}^#p zUg-vL!b&#vPFhbBKD#N5x42`1^0?D{O$M_~YFx;x&7|j+!9|+y7rx zqMf_a-rv;h5k<>5f~gQRT0ihfmZ-MHQpc)%rT06kc_Gq#3vj@vOh)V;xwyG1qGcYh zrJAH&A1>Au{`-~cSyFIRpUht|N`>xcRAXR1t&E=v?8AnIt9A zO-Jaua72Z&#CC-3SP0!P%3nMK`JA_xy9z(mb4oVEa^t`glO3xyA%Z44Yz*e3@O4i$ z*NjmAAk5L@xet}A;P-aThg)>Gk>GyNq9G(*?gXY!`mL#J%A?{ygGL?>G4f~YID7R3 zT2#XDdg(&f1y1F#W3P7i)vhGB0X&?a6uH@%t!oDYTrD{Q&VX3bl+C6;KSg+V(gmFG z)acrvU%N(V~+m>AfKh0UUxo5ki%Ywt*l?v`QO zdcPy>oklaHnFP+Nd7w$z6wu1+QY{BnvN(-sZsU$G zt?PRb6r7}vufVLuc@vwg21YB$6I=e!)F2GI_ltw&eR?B|YB@z%Lb-%?LW+%vr{OJS z?(6UdSAvctJC%o~k&tgHYz@k`UOl}Ku2EM11gkY6^42SMsDI;URDp(U0{hsY=JeMk zuq=i6o3t|3L(dhTdb-%SGpGg446611WR}sMaWDE6N+`NBU*YSg9`#zcQ)0u;y{|3} zWJ+aYrmJk5DBH%JRtB##v$5xn<^9%HY@bG!Ogm;e$GB2*iQYKRQ(=F6^LnXFuGDw8 zQNl(9AM)*@JRi5>E)xn&dqHPUhdX|~@=$|5<4uz7Bh=-Vs4geV0>bwaMqelwsMD-8 zgF$+4G1t@p;-itJvqD;_t)Ep{Of+<*F!>SJ{Med|-NQ z2$D_8lH62!kqG@)r(x{X$-AbC*>B|w*%q&2@P}MHyM+}u-~z!(zPzUK{N1_hCuMxj*9vs`@f&KD$d(m6=4-h}by9unzpV49=Vi?dU0C%xp%;M_ z7@zc#p{~aH%5)VcmewmeWfcZpPB@yBm5wAe#e7la?sI8Qm{+_lAu-SXr=pnzZq6TQ zK=}ne^rod++kY5N+pf1rL%mVm&3|k#xZ+fjcwX(;oR-kad}5-`Y)K+)wIEUFrWAR@ z(%A4x(CfJRv=f8x1m(8mcBJOtgls0=@V-CR(wX9uFT8VNM`Dg|U(q?CSDD?Z?ZPwF zBodFG{IjPYj~{yz>0xIT2`Ac~y#=kfWOJ!7J+HFH-muoH?>W%~_0&BgrqgS9MSLXJ z?O2fwtbC;WBqK{BSn@kGp3@@V(K7A2Q}ycOYf`!57cM9a#=fXR63W-s@ypLK*@x1U z&B&m!ubh$vam$3<6217F?8cZne`N*8C8cQIM}29(sUrB^v&nnA_u!XaE$C>P(C0wB z`mUwA5CNuj^P+~i$gBDF&htlIpE-Cmzbot;eRw60KYritlI_HJ>gGnpU^i~+^0gkh z64#rJK?i*`8jQo0A5*t}iKWGC{#%kG`1MBsezQHOr1@0=14 zz~k+PB=U>=zUfhg4Nf?Qr{DN472oNE>6uH|&udobf-IU#H#V9ZHD>Qpi7-x$_Sk<& zW5wia@vQ?=r?9$4&5<}C{yI8(G@j&dp>V&@Hn+V+zZM}aC#p3LG{R|i3k1)=YH0P+ zK9tkqnV00s#y1UXQf`hL!~hw4p}SHM=>gI9$mZwoRN2;h&BBc!}KGv>Aw#bMNrgb z=*}0azjA*QxbE*3O)v_2xlYyiJfN@ZK$|%0X(D7EUvuY9t60Yy&LoGDg-gFS1%55D zW3FX=QLi~%B{>j4+E@x#!+f{w>z@^&W(P6_4C@HLysvnW>Nk? z+(>AD(x^h6)QBc4&1{YFo!8MzdG&58x!5DFMpvI2@F8axj_%i}1HBLWa3Afy+TUj` zTlR3yVoklb8}-9#m+NqMhT7qs=ri=0bwWrqDgNlww$25xK^E$7k(=N{x{LR3dsuoQ zMD+HY^%ihgNx+uqpqf22s+FU5AUjj=fXl_45kVvb;wcM( z9A@^blC@y<7lc4=)A;WIzi+qcibF}RB=yasx4Hk$gfdivB zpiBr%5my1_#&AHj7*iwwdX4D=wNO@%-e4Y7EG96|Jf^N zx_}(sBj7h@3M4>T>T$sPkN*@xH3Y&gvEUF@9|*Mn8*+iiX==cTE9g!$2b76m6U`b3 zC4$IFO`w7ZnorsRCq0;h5a{491ujnFfKS&!pK2_qG^GoK`LN*Rq$pTDg#o5-vcio4 zUXV5c2RWuOfK(tTKCOY>vpun=P*@OCAPHtq>jU+nEXcTv1Y^hG*nj#gC7{ z0hd2n@FMdp12Z#r&+ERY!2BZSGm`-q=W)P#131tn1L`c`0FHLhW5EWH?E<%k@ZjbM t97HfMz;-t{JgmtI1DN4(FPO?W14#6Na}0%pN)RPT7Xkut?fZBBe*sCPA