diff --git a/graphdb/graphcli/src/main/java/me/schaertl/graphcli/GraphDB.java b/graphdb/graphcli/src/main/java/me/schaertl/graphcli/GraphDB.java new file mode 100644 index 0000000000000000000000000000000000000000..2b3cc447e76cca6e4322934effe4dde7dd667806 --- /dev/null +++ b/graphdb/graphcli/src/main/java/me/schaertl/graphcli/GraphDB.java @@ -0,0 +1,127 @@ +package me.schaertl.graphcli; + +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.repository.RepositoryConnection; +import org.eclipse.rdf4j.repository.RepositoryException; +import org.eclipse.rdf4j.repository.manager.RemoteRepositoryManager; +import org.eclipse.rdf4j.repository.manager.RepositoryManager; + +/** + * Wrapper around various RDF4J methods. Represents a connection to a GraphDB + * instance on the network. + * + * For creating a new connection, simply create a new object of this class. To + * then close all associated resources, call {@link GraphDB#close}. As this class + * implements {@link AutoCloseable}, you can also use the convenient try-with-resources. + */ +public class GraphDB implements AutoCloseable { + private final RepositoryManager manager; + private final Repository repository; + private final RepositoryConnection connection; + + private boolean closed = false; + + /** + * Establish a new connection to a remote GraphDB instance. + * + * @param serverURL The URL under which the instance is reachable. + * @param repository The repository to connect to. + * @throws RepositoryException If connecting to the server or repository failed. + */ + public GraphDB(String serverURL, String repository) throws RepositoryException { + this.manager = new RemoteRepositoryManager(serverURL); + this.manager.init(); + + this.repository = this.manager.getRepository(repository); + if (this.repository == null) { + this.manager.shutDown(); + throw new RepositoryException(String.format("no repository with name %s", repository)); + } + + try { + this.connection = this.repository.getConnection(); + } finally { + this.manager.shutDown(); + this.repository.shutDown(); + } + } + + /** + * Release all associated resources + * + * @throws IllegalStateException If this method called multiple times on a single object. + */ + @Override + public synchronized void close() throws Exception { + if (this.closed) { + throw new IllegalStateException("multiple calls to close()"); + } + + this.closed = true; + + // What comes now is very very ugly. From what I can tell the way + // the RDF4j API works this is the only way to make sure that everything + // gets closed properly. Bummer. + + Exception error = null; + + try { + if (this.connection != null) { + this.connection.close(); + } + } catch (Exception e) { + error = e; + } + + try { + if (this.repository != null) { + this.repository.shutDown(); + } + } catch (Exception e) { + if (error != null) { + error = e; + } + } + + try { + if (this.manager != null) { + this.manager.shutDown(); + } + } catch (Exception e) { + if (error != null) { + error = e; + } + } + + if (error != null) { + throw error; + } + } + + /** + * Return a connection for interaction with the underlying database. + * + * @throws IllegalStateException If {@link GraphDB#close} was called on this object before. + */ + public synchronized RepositoryConnection connection() { + if (this.closed) { + throw new IllegalStateException("called connection() after close()"); + } + + return this.connection; + } + + /** + * Return a factory for create new objects. + * + * @throws IllegalStateException If {@link GraphDB#close} was called on this object before. + */ + public synchronized ValueFactory factory() { + if (this.closed) { + throw new IllegalStateException("called factory() after close()"); + } + + return this.repository.getValueFactory(); + } +} diff --git a/graphdb/graphcli/src/main/java/me/schaertl/graphcli/Main.java b/graphdb/graphcli/src/main/java/me/schaertl/graphcli/Main.java index 39610402de327fc9a5ac253bb3907ed99a4d7723..8143cb9bdd1b54c48fa6a019b4b10fd2ab157402 100644 --- a/graphdb/graphcli/src/main/java/me/schaertl/graphcli/Main.java +++ b/graphdb/graphcli/src/main/java/me/schaertl/graphcli/Main.java @@ -1,64 +1,47 @@ package me.schaertl.graphcli; -import org.eclipse.rdf4j.model.Resource; -import org.eclipse.rdf4j.model.impl.TreeModel; -import org.eclipse.rdf4j.model.vocabulary.RDF; -import org.eclipse.rdf4j.repository.Repository; +import org.eclipse.rdf4j.model.Statement; import org.eclipse.rdf4j.repository.RepositoryConnection; -import org.eclipse.rdf4j.repository.config.RepositoryConfig; -import org.eclipse.rdf4j.repository.config.RepositoryConfigSchema; -import org.eclipse.rdf4j.repository.manager.LocalRepositoryManager; -import org.eclipse.rdf4j.repository.manager.RemoteRepositoryManager; -import org.eclipse.rdf4j.repository.manager.RepositoryManager; -import org.eclipse.rdf4j.rio.RDFFormat; -import org.eclipse.rdf4j.rio.RDFParser; -import org.eclipse.rdf4j.rio.Rio; -import org.eclipse.rdf4j.rio.helpers.StatementCollector; +import org.eclipse.rdf4j.repository.RepositoryResult; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; public class Main { - private static void hello() throws IOException { - // Code taken from http://graphdb.ontotext.com/documentation/standard/using-graphdb-with-the-rdf4j-api.html + private static final String SERVER_URL = "http://rdf:7200"; + private static final String REPOSITORY = "dump"; + private static final int LIMIT = 100; - // Instantiate a local repository manager and initialize it - final RepositoryManager repositoryManager = new RemoteRepositoryManager("http://rdf:7200"); - repositoryManager.initialize(); + private static void hello() throws Exception { + try (final GraphDB db = new GraphDB(SERVER_URL, REPOSITORY)) { + final RepositoryConnection connection = db.connection(); - // Instantiate a repository graph model - // final TreeModel graph = new TreeModel(); + final RepositoryResult<Statement> result = connection.getStatements(null, ULO.INDUCTIVE_ON, null, true); - // Read repository configuration file - // InputStream config = EmbeddedGraphDB.class.getResourceAsStream("/repo-defaults.ttl"); - // RDFParser rdfParser = Rio.createParser(RDFFormat.TURTLE); - // rdfParser.setRDFHandler(new StatementCollector(graph)); - // rdfParser.parse(config, RepositoryConfigSchema.NAMESPACE); - // config.close(); - - // Retrieve the repository node as a resource - // Resource repositoryNode = GraphUtil.getUniqueSubject(graph, RDF.TYPE, RepositoryConfigSchema.REPOSITORY); - - // Create a repository configuration object and add it to the repositoryManager - // RepositoryConfig repositoryConfig = RepositoryConfig.create(graph, repositoryNode); - // repositoryManager.addRepositoryConfig(repositoryConfig); - - // Get the repository from repository manager, note the repository id set in configuration .ttl file - final Repository repository = repositoryManager.getRepository("chem"); - - // Open a connection to this repository - final RepositoryConnection repositoryConnection = repository.getConnection(); - - // ... use the repository + for (Statement s : take(result, LIMIT)) { + System.out.printf("%s INDUCTIVE ON %s", s.getSubject(), s.getObject()); + } + } + } - // Shutdown connection, repository and manager - repositoryConnection.close(); - repository.shutDown(); - repositoryManager.shutDown(); + /** + * Return the first n results from result. + * + * @param result The result from which the results will be returned. + * @param n The maximum number of items to return. + */ + private static List<Statement> take(RepositoryResult<Statement> result, int n) { + final List<Statement> l = new ArrayList<>(n); + + for (int i = 0; i < LIMIT && result.hasNext(); i++) { + final Statement s = result.next(); + l.add(s); + } + + return l; } - public static void main(String[] args) throws IOException { + public static void main(String[] args) throws Exception { Main.hello(); System.out.println("done running the program"); } diff --git a/graphdb/graphcli/src/main/java/me/schaertl/graphcli/ULO.java b/graphdb/graphcli/src/main/java/me/schaertl/graphcli/ULO.java new file mode 100644 index 0000000000000000000000000000000000000000..ae4d9da24345376babe415713e6fa680eb5449fe --- /dev/null +++ b/graphdb/graphcli/src/main/java/me/schaertl/graphcli/ULO.java @@ -0,0 +1,39 @@ +package me.schaertl.graphcli; + +import org.eclipse.rdf4j.model.IRI; +import org.eclipse.rdf4j.model.Namespace; +import org.eclipse.rdf4j.model.ValueFactory; +import org.eclipse.rdf4j.model.impl.SimpleNamespace; +import org.eclipse.rdf4j.model.impl.SimpleValueFactory; +import org.eclipse.rdf4j.model.vocabulary.FOAF; + +/** + * Constants for use with ULO, the Upper Library Ontology [1]. + * + * [1] https://gl.mathhub.info/ulo/ulo/-/tree/master/ + */ +public class ULO { + private ULO() {} + + /** + * The ULO namespace: https://mathhub.info/ulo + */ + public static final String NAMESPACE = "https://mathhub.info/ulo"; + + /** + * The recommended prefix for the ULO namespace: "ulo" + */ + public static final String PREFIX = "ulo"; + + /** + * An immutable {@link Namespace} constant that represents the ULO namespace. + */ + public static final Namespace NS = new SimpleNamespace(PREFIX, NAMESPACE); + + public final static IRI INDUCTIVE_ON; + + static { + final ValueFactory factory = SimpleValueFactory.getInstance(); + INDUCTIVE_ON = factory.createIRI(ULO.NAMESPACE, "inductive-on"); + } +} diff --git a/timeline/week19.txt b/timeline/week19.txt index 764cd52ab3b86b2c9cafb5d380617ed4fe0bc5f7..ff831237829ad9feb59667ee0e049837f6904004 100644 --- a/timeline/week19.txt +++ b/timeline/week19.txt @@ -22,7 +22,9 @@ Week 19 (04.05.-10.05.) the programming interface. The docs are in Java, switching to Scala should not be hard. - [ ] Look at the RDF4J tutorial [1] + [x] Look at the RDF4J tutorial [1] + + [ ] Create ULO class in the vein of [2] [ ] familiarize w/ MathHub infastructure @@ -49,3 +51,4 @@ References ========== [1] https://rdf4j.org/documentation/programming/ +[2] https://jar-download.com/artifacts/org.eclipse.rdf4j/rdf4j-model/3.0.3/source-code/org/eclipse/rdf4j/model/vocabulary/FOAF.java