diff --git a/README.md b/README.md index 386fde6..31fe52e 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,11 @@ # Ontology Converter v1.0 -## A simple command-line utility to convert any rdf graph to OWL2-DL ontology. -This is a kind of [ONT-API](https://github.com/avicomp/ont-api) extension, without a claim. Can work both with single ontology file source and with directory containing dependent or independent sources. -The utility automatically transforms the source RDF Graph to the OWL2 DL syntax according to the inner rules and command-line options. For example, if there is no `owl:Ontology` section inside rdf-graph, which is required by OWL, an anonymous ontology header will be generated. +## A simple command-line utility to convert any RDF graph to OWL2-DL ontology. +This is a kind of [ONT-API](https://github.com/avicomp/ont-api) extension with intentionally straightforward realisation. +Can work both with single ontology file source and with directory containing dependent or independent sources. +The utility automatically transforms the source RDF Graph to the OWL2 DL syntax according to the internal rules and command-line options. +For example, if there is no `owl:Ontology` section inside rdf-graph, which is required by OWL, an anonymous ontology header will be generated. +This is a tool, not a library, and, therefore, it is available only in the form of code and prebuilt jar (see [/releases](https://github.com/sszuev/ont-converter/releases)). ### Usage: `java -jar ont-converter.jar [-f] [-h] -i [-if ] -o -of [-p <0|1|2>] [-r] [-s] [-v] [-w]` @@ -114,5 +117,8 @@ where * java1.8 * maven to build (`mvn package`) +### Issues: +In case of any issue (for example the program hangs), please report it into the [/ont-converter/issues](https://github.com/sszuev/ont-converter/issues) page, but only if you really sure that the problem is in the program, not in the underlying API. Otherwise please refer to the [/ont-api/issues](https://github.com/avicomp/ont-api/issues) page. + ### Dependencies: - [ONT-API](https://github.com/avicomp/ont-api) (__version 1.1.0-SNAPSHOT__) \ No newline at end of file + [ONT-API](https://github.com/avicomp/ont-api) (__version 1.4.0-SNAPSHOT__) \ No newline at end of file diff --git a/pom.xml b/pom.xml index 7e67bef..87957c4 100644 --- a/pom.xml +++ b/pom.xml @@ -13,6 +13,10 @@ 1.8 UTF-8 true + 1.4.0-SNAPSHOT + 3.8.0 + 5.1.7 + 1.7.25 @@ -32,27 +36,27 @@ ru.avicomp ontapi - 1.1.0-SNAPSHOT + ${version.ontapi} org.apache.jena jena-csv - 3.6.0 + ${version.jena} net.sourceforge.owlapi owlapi-parsers - 5.1.4 + ${version.owlapi} net.sourceforge.owlapi owlapi-rio - 5.1.4 + ${version.owlapi} net.sourceforge.owlapi owlapi-oboformat - 5.1.4 + ${version.owlapi} org.topbraid @@ -69,10 +73,15 @@ commons-lang 2.6 + + org.slf4j + slf4j-api + ${version.slf4j} + org.slf4j slf4j-log4j12 - 1.7.22 + ${version.slf4j} diff --git a/src/main/java/com/github/sszuev/Args.java b/src/main/java/com/github/sszuev/Args.java index c80571b..3ca9274 100644 --- a/src/main/java/com/github/sszuev/Args.java +++ b/src/main/java/com/github/sszuev/Args.java @@ -5,9 +5,8 @@ import org.apache.commons.lang.ArrayUtils; import org.apache.commons.lang3.StringUtils; import ru.avicomp.ontapi.OntFormat; -import ru.avicomp.ontapi.jena.impl.configuration.Configurable; -import ru.avicomp.ontapi.jena.impl.configuration.OntModelConfig; -import ru.avicomp.ontapi.jena.impl.configuration.OntPersonality; +import ru.avicomp.ontapi.jena.impl.conf.OntModelConfig; +import ru.avicomp.ontapi.jena.impl.conf.OntPersonality; import java.io.IOException; import java.io.PrintWriter; @@ -32,12 +31,20 @@ public class Args { private static final int READ_WRITE_COL_LENGTH = 13; private final Path input, output; private final OntFormat outFormat, inFormat; - private final Configurable.Mode personality; + private final OntModelConfig.StdMode personality; private final boolean spin, force, refine, verbose, webAccess; private boolean outDir, inDir; - private Args(Path input, Path output, OntFormat outFormat, OntFormat inFormat, Configurable.Mode personality, - boolean spin, boolean force, boolean clear, boolean verbose, boolean webAccess) { + private Args(Path input, + Path output, + OntFormat outFormat, + OntFormat inFormat, + OntModelConfig.StdMode personality, + boolean spin, + boolean force, + boolean clear, + boolean verbose, + boolean webAccess) { this.input = input; this.output = output; this.outFormat = outFormat; @@ -67,7 +74,7 @@ public static Args parse(String... args) throws IOException, IllegalArgumentExce // parse OntFormat outputFormat = parseOutputFormat(cmd); OntFormat inputFormat = parseInputFormat(cmd); - Configurable.Mode mode = parsePersonalities(cmd); + OntModelConfig.StdMode mode = parsePersonalities(cmd); Path in = Paths.get(cmd.getOptionValue(Opts.INPUT.longName)).toRealPath(); Path out = Paths.get(cmd.getOptionValue(Opts.OUTPUT.longName)); @@ -111,13 +118,14 @@ private static OntFormat parseOutputFormat(CommandLine cmd) { return res; } - private static Configurable.Mode parsePersonalities(CommandLine cmd) { + private static OntModelConfig.StdMode parsePersonalities(CommandLine cmd) { if (!cmd.hasOption(Opts.PUNNING.longName)) { - return Configurable.Mode.LAX; + return OntModelConfig.StdMode.LAX; } String val = cmd.getOptionValue(Opts.PUNNING.longName); + OntModelConfig.StdMode[] values = OntModelConfig.StdMode.values(); try { - return Configurable.Mode.values()[Configurable.Mode.values().length - Integer.parseInt(val)]; + return values[values.length - Integer.parseInt(val)]; } catch (NumberFormatException | IndexOutOfBoundsException e) { throw new IllegalArgumentException("Wrong --" + Opts.PUNNING.longName + ":" + val, e); } @@ -129,7 +137,8 @@ private static String help(Options opts, boolean usage) { sb.append("A simple command-line utility to convert any rdf graph to OWL2-DL ontology.").append("\n"); } StringWriter sw = new StringWriter(); - new HelpFormatter().printHelp(new PrintWriter(sw), 74, "java -jar " + JAR_NAME, "options:", opts, 1, 3, null, true); + new HelpFormatter().printHelp(new PrintWriter(sw), 74, "java -jar " + JAR_NAME, + "options:", opts, 1, 3, null, true); sb.append(sw); if (usage) { sb.append("Full list of supported formats:").append("\n"); diff --git a/src/main/java/com/github/sszuev/Main.java b/src/main/java/com/github/sszuev/Main.java index 626f4d3..7fbfabc 100644 --- a/src/main/java/com/github/sszuev/Main.java +++ b/src/main/java/com/github/sszuev/Main.java @@ -103,7 +103,9 @@ private static void processDir(Args args) throws IOException, OntApiException { } } - private static OWLOntologyID load(OntologyManager manager, OWLOntologyDocumentSource source, boolean ignoreErrors) throws OntApiException { + private static OWLOntologyID load(OntologyManager manager, + OWLOntologyDocumentSource source, + boolean ignoreErrors) throws OntApiException { try { OWLOntology o = Managers.loadOntology(manager, source); return o.getOntologyID(); diff --git a/src/main/java/com/github/sszuev/spin/SpinTransform.java b/src/main/java/com/github/sszuev/spin/SpinTransform.java index 68bacdf..1f5f974 100644 --- a/src/main/java/com/github/sszuev/spin/SpinTransform.java +++ b/src/main/java/com/github/sszuev/spin/SpinTransform.java @@ -88,7 +88,7 @@ public void perform() { .map(Statement::getObject) .filter(RDFNode::isURIResource) .map(RDFNode::asResource) - .findFirst().orElseThrow(OntJenaException.supplier("No type for " + literal)); + .findFirst().orElseThrow(() -> new OntJenaException("No type for " + literal)); Set remove = Models.getAssociatedStatements(query); remove.stream() .filter(s -> !(RDF.type.equals(s.getPredicate()) && type.equals(s.getObject()))) diff --git a/src/main/java/com/github/sszuev/utils/Formats.java b/src/main/java/com/github/sszuev/utils/Formats.java index 5dae437..30ca49f 100644 --- a/src/main/java/com/github/sszuev/utils/Formats.java +++ b/src/main/java/com/github/sszuev/utils/Formats.java @@ -1,11 +1,5 @@ package com.github.sszuev.utils; -import java.util.List; -import java.util.Objects; -import java.util.Optional; -import java.util.stream.Collectors; -import java.util.stream.Stream; - import org.apache.jena.lang.csv.ReaderRIOTFactoryCSV; import org.apache.jena.riot.Lang; import org.apache.jena.riot.RDFParserRegistry; @@ -13,12 +7,17 @@ import org.semanticweb.owlapi.model.IRI; import org.semanticweb.owlapi.model.OWLDocumentFormat; import org.semanticweb.owlapi.model.OWLOntology; - import ru.avicomp.ontapi.OntFormat; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.stream.Collectors; +import java.util.stream.Stream; + /** * Utils to work with {@link OntFormat format}s. - * + *

* Created by @szuev on 11.01.2018. */ @SuppressWarnings("WeakerAccess") @@ -40,6 +39,7 @@ public static OntFormat find(String key) { /** * Returns format aliases + * * @param f {@link OntFormat}, not null * @return List of stings corresponding specified format. */ @@ -52,6 +52,7 @@ public static List aliases(OntFormat f) { /** * Registers {@link Lang#CSV} in jena system. * This operation enables {@link OntFormat#CSV} for reading operations. + * * @see #unregisterJenaCSV() */ public static void registerJenaCSV() { @@ -61,6 +62,7 @@ public static void registerJenaCSV() { /** * unregisters csv format + * * @see #registerJenaCSV() */ public static void unregisterJenaCSV() { @@ -69,6 +71,7 @@ public static void unregisterJenaCSV() { /** * Determines is the specified resource can be treated as csv-file. + * * @param iri {@link IRI} * @return true if the resource has extension '.csv' */ diff --git a/src/main/java/com/github/sszuev/utils/IRIs.java b/src/main/java/com/github/sszuev/utils/IRIs.java index e7f65ad..d3c8dc0 100644 --- a/src/main/java/com/github/sszuev/utils/IRIs.java +++ b/src/main/java/com/github/sszuev/utils/IRIs.java @@ -1,5 +1,14 @@ package com.github.sszuev.utils; +import org.apache.commons.io.FilenameUtils; +import org.semanticweb.owlapi.io.FileDocumentSource; +import org.semanticweb.owlapi.io.IRIDocumentSource; +import org.semanticweb.owlapi.io.OWLOntologyDocumentSource; +import org.semanticweb.owlapi.model.IRI; +import org.semanticweb.owlapi.model.OWLOntology; +import org.semanticweb.owlapi.model.OWLOntologyID; +import ru.avicomp.ontapi.OntFormat; + import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; @@ -11,19 +20,9 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import org.apache.commons.io.FilenameUtils; -import org.semanticweb.owlapi.io.FileDocumentSource; -import org.semanticweb.owlapi.io.IRIDocumentSource; -import org.semanticweb.owlapi.io.OWLOntologyDocumentSource; -import org.semanticweb.owlapi.model.IRI; -import org.semanticweb.owlapi.model.OWLOntology; -import org.semanticweb.owlapi.model.OWLOntologyID; - -import ru.avicomp.ontapi.OntFormat; - /** * The helper to work with {@link IRI}s, usually related to local files. - * + *

* Created by @szuev on 15.01.2018. */ public class IRIs { @@ -41,6 +40,7 @@ public static boolean hasExtension(String extension, IRI iri) { /** * Returns all files from a directory, most deep go first, empty files are excluded + * * @param dir {@link Path}, the directory (but can be file also) * @return List of {@link IRI}s * @throws IOException if any i/o error occurs. @@ -52,7 +52,8 @@ public static List getFiles(Path dir) throws IOException { /** * Walks through directory, the output stream are sorted in descending order of file depth - * @param dir {@link Path} + * + * @param dir {@link Path} * @param holder {@link IOException} to collect any internal (file-specified) exceptions * @return Stream of {@link IRI}s * @throws IOException if i/o error occurs when read directory @@ -85,8 +86,9 @@ public static Stream walk(Path dir, IOException holder) throws IOException /** * Creates a document-source from iri and format + * * @param document {@link IRI}, not null - * @param format {@link OntFormat}, nullable + * @param format {@link OntFormat}, nullable * @return {@link OWLOntologyDocumentSource} */ public static OWLOntologyDocumentSource toSource(IRI document, OntFormat format) { diff --git a/src/main/java/com/github/sszuev/utils/Managers.java b/src/main/java/com/github/sszuev/utils/Managers.java index 433c7c3..70fb40e 100644 --- a/src/main/java/com/github/sszuev/utils/Managers.java +++ b/src/main/java/com/github/sszuev/utils/Managers.java @@ -12,8 +12,8 @@ import org.slf4j.LoggerFactory; import ru.avicomp.ontapi.*; import ru.avicomp.ontapi.config.OntConfig; -import ru.avicomp.ontapi.jena.impl.configuration.OntModelConfig; -import ru.avicomp.ontapi.jena.impl.configuration.OntPersonality; +import ru.avicomp.ontapi.jena.impl.conf.OntModelConfig; +import ru.avicomp.ontapi.jena.impl.conf.OntPersonality; import ru.avicomp.ontapi.transforms.GraphTransformers; import java.io.IOException; @@ -49,7 +49,8 @@ public static OntologyManager newManager() { * all punnings are allowed, * no transformations. * any errors while collecting axioms are ignored - * (note: there are no processing axioms if it is valid rdf-document which can be parse by jena, otherwise true OWL-Parsers are called) + * (note: there are no processing axioms if it is valid rdf-document which can be parse by jena, + * otherwise true OWL-Parsers are called) * * @return {@link OntologyManager} */ @@ -67,13 +68,17 @@ public static OntologyManager createSoftManager() { /** * Creates a manager without web-access * - * @param personality {@link OntPersonality} personalities, can be null - * @param map {@link IRIMap} the mapper - * @param force true to force load/store ontologies - * @param transformSpin if true run {@link SpinTransform} to fix bulk []-List based SPARQL-Queries, which can be present in spin-library rdf-ontologies. + * @param personality {@link OntPersonality} personalities, can be null + * @param map {@link IRIMap} the mapper + * @param force true to force load/store ontologies + * @param transformSpin if true run {@link SpinTransform} to fix bulk []-List based SPARQL-Queries, + * which can be present in spin-library rdf-ontologies. * @return {@link OntologyManager} */ - public static OntologyManager createManager(OntPersonality personality, IRIMap map, boolean force, boolean transformSpin) { + public static OntologyManager createManager(OntPersonality personality, + IRIMap map, + boolean force, + boolean transformSpin) { OntologyManager manager = createManager(personality, force, transformSpin); OntConfig config = manager.getOntologyConfigurator(); config.setSupportedSchemes(Collections.singletonList(OntConfig.DefaultScheme.FILE)); @@ -83,10 +88,10 @@ public static OntologyManager createManager(OntPersonality personality, IRIMap m } /** - * @param personality {@link OntPersonality} personalities, can be null - * @param allowFollowImports true to prohibit web-traversing for owl:imports - * @param force true to ignore missing imports skip reading wrong axioms. - * @param transformSpin true to enable spin transformation + * @param personality {@link OntPersonality} personalities, can be null + * @param allowFollowImports true to prohibit web-traversing for owl:imports + * @param force true to ignore missing imports skip reading wrong axioms. + * @param transformSpin true to enable spin transformation * @return {@link OntologyManager} */ public static OntologyManager createManager(OntPersonality personality, @@ -104,9 +109,9 @@ public static OntologyManager createManager(OntPersonality personality, } /** - * @param personality {@link OntPersonality} personalities, can be null - * @param force true to ignore missing imports and skip reading wrong axioms. - * @param transformSpin true to enable spin transformation + * @param personality {@link OntPersonality} personalities, can be null + * @param force true to ignore missing imports and skip reading wrong axioms. + * @param transformSpin true to enable spin transformation * @return {@link OntologyManager} */ public static OntologyManager createManager(OntPersonality personality, boolean force, boolean transformSpin) { @@ -120,7 +125,8 @@ public static OntologyManager createManager(OntPersonality personality, boolean config.setGraphTransformers(transformers.addFirst(SpinTransform::new)); } if (force) { - config.setMissingImportHandlingStrategy(MissingImportHandlingStrategy.SILENT).setIgnoreAxiomsReadErrors(true); + config.setMissingImportHandlingStrategy(MissingImportHandlingStrategy.SILENT) + .setIgnoreAxiomsReadErrors(true); } return manager; } @@ -140,12 +146,12 @@ public static void copyOntologies(OntologyManager from, OntologyManager to, bool src.forEach(o -> { IRI name = IRIs.toName(o); LOGGER.trace("Copy ontology {}", name); - try { - to.copyOntology(o, OntologyCopy.DEEP); - } catch (OWLOntologyCreationException e) { - ex.addSuppressed(e); - } - }); + try { + to.copyOntology(o, OntologyCopy.DEEP); + } catch (OWLOntologyCreationException e) { + ex.addSuppressed(e); + } + }); if (!ignoreExceptions && ex.getSuppressed().length != 0) { throw ex; } @@ -166,7 +172,8 @@ public static OntologyManager copyManager(OntologyManager from) { /** * Loads an ontology to manager. - * Since {@link org.apache.jena.riot.Lang#CSV} is very tolerant (almost all textual files could be treated as CSV table) + * Since {@link org.apache.jena.riot.Lang#CSV} is very tolerant + * (almost all textual files could be treated as CSV table) * it is excluded from consideration. There is only exception - if the file has extension '.csv' * * @param manager {@link OntologyManager} the manager to put ontology @@ -174,9 +181,11 @@ public static OntologyManager copyManager(OntologyManager from) { * @return {@link OntologyModel} the ontology * @throws OWLOntologyCreationException in case of any error */ - public static OntologyModel loadOntology(OntologyManager manager, OWLOntologyDocumentSource source) throws OWLOntologyCreationException { + public static OntologyModel loadOntology(OntologyManager manager, + OWLOntologyDocumentSource source) throws OWLOntologyCreationException { Optional format = Formats.format(source); - boolean isCvs = (!format.isPresent() && Formats.isCSV(source.getDocumentIRI())) || format.filter(s -> Objects.equals(s, OntFormat.CSV)).isPresent(); + boolean isCvs = (!format.isPresent() && Formats.isCSV(source.getDocumentIRI())) + || format.filter(s -> Objects.equals(s, OntFormat.CSV)).isPresent(); try { if (isCvs) { Formats.registerJenaCSV(); @@ -188,7 +197,8 @@ public static OntologyModel loadOntology(OntologyManager manager, OWLOntologyDoc } /** - * Creates a collection of {@link org.semanticweb.owlapi.model.OWLOntologyIRIMapper} by traversing the specified directory. + * Creates a collection of {@link org.semanticweb.owlapi.model.OWLOntologyIRIMapper} + * by traversing the specified directory. * Each map will content unique ontology-id+file-iri pairs. * * @param dir {@link Path} the file (usually directory) @@ -213,7 +223,10 @@ public static List createMappings(Path dir, OntFormat format) throws IOE * @throws IOException if any i/o problem occurs. * @throws OntApiException if file is unparsable or unloadable */ - public static List loadDirectory(Path dir, OntFormat format, Supplier factory, boolean continueIfError) throws IOException, OntApiException { + public static List loadDirectory(Path dir, + OntFormat format, + Supplier factory, + boolean continueIfError) throws IOException, OntApiException { List files = IRIs.getFiles(dir); List res = new ArrayList<>(); while (true) {