package swiss.sib.sparql.playground.repository.impl; import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Map; import javax.annotation.PostConstruct; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.openrdf.model.Model; import org.openrdf.model.Resource; import org.openrdf.model.Statement; import org.openrdf.model.impl.LinkedHashModel; import org.openrdf.query.MalformedQueryException; import org.openrdf.query.Query; import org.openrdf.query.QueryEvaluationException; import org.openrdf.query.QueryLanguage; import org.openrdf.query.TupleQuery; import org.openrdf.query.TupleQueryResult; import org.openrdf.repository.Repository; import org.openrdf.repository.RepositoryConnection; import org.openrdf.repository.RepositoryException; import org.openrdf.repository.RepositoryResult; import org.openrdf.repository.sail.SailRepository; import org.openrdf.rio.RDFFormat; import org.openrdf.rio.RDFHandlerException; import org.openrdf.rio.RDFParseException; import org.openrdf.rio.Rio; import org.openrdf.sail.memory.MemoryStore; import org.openrdf.sail.nativerdf.NativeStore; import org.springframework.beans.factory.InitializingBean; import swiss.sib.sparql.playground.Application; import swiss.sib.sparql.playground.exception.SparqlTutorialException; import swiss.sib.sparql.playground.repository.SesameRepository; import info.aduna.iteration.Iterations; /** * RDF data store for sesame * * @author Daniel Teixeira http://github.com/ddtxra * */ @org.springframework.stereotype.Repository public class SesameRepositoryImpl implements SesameRepository, InitializingBean { private static final Log logger = LogFactory.getLog(SesameRepositoryImpl.class); // Read documentation: http://rdf4j.org/sesame/2.7/docs/users.docbook?view // http://www.cambridgesemantics.com/semantic-university/sparql-by-example private Repository rep = null; private SailRepository testRepo; private RepositoryConnection conn = null; @Override public Query prepareQuery(String sparqlQuery) { try { return conn.prepareQuery(QueryLanguage.SPARQL, sparqlQuery); } catch (RepositoryException | MalformedQueryException e) { e.printStackTrace(); throw new SparqlTutorialException(e); } } @PostConstruct public void init() throws Exception { boolean nativeConfig = (System.getProperty("repository.type") != null) && (System.getProperty("repository.type").equals("native")); if (nativeConfig) { logger.info("Found repository type native property!"); } // If native configuration is set File sesameDataFolder = null; File sesameDataValueFile = null; if (nativeConfig) { sesameDataFolder = new File(Application.FOLDER + "/sesame-db"); sesameDataValueFile = new File(sesameDataFolder.getPath() + "/values.dat"); logger.info("Initializing native repository in " + sesameDataFolder); rep = new SailRepository(new NativeStore(sesameDataFolder)); } else { // otherwise take memory logger.info("Initializing in memory repository"); rep = new SailRepository(new MemoryStore()); } File ttlFile = new File(Application.FOLDER + "/ttl-data"); // if if it not native (memory) just load it. // if it is native and the data is still not there.... if (!nativeConfig) { rep.initialize(); logger.info("Loading turtle files from " + ttlFile); addTTLFiles(ttlFile, rep.getConnection()); } else if (nativeConfig && !sesameDataValueFile.exists()) { rep.initialize(); logger.info("No previous sesame repository found in " + sesameDataValueFile); logger.info("Loading turtle files from " + ttlFile); logger.info("Depending on the number of triplets, this may take some time to load the first time, please be patient ...."); addTTLFiles(ttlFile, rep.getConnection()); } else { rep.initialize(); logger.info("Sesame repository already found in " + sesameDataValueFile); logger.info("Skipping to load turtle files. Remove " + sesameDataFolder + " folder if you want to reload turtle files"); } // logger.info("Counting number of triplets..."); // logger.info("Repository contains " + countTriplets() + " triplets"); testRepo = new SailRepository(new MemoryStore()); testRepo.initialize(); } private static void addTTLFiles(final File folder, RepositoryConnection conn) throws RDFParseException, RepositoryException, IOException { long start = System.currentTimeMillis(); for (final File fileEntry : folder.listFiles()) { if (!fileEntry.isDirectory()) { logger.debug("Loading " + fileEntry); conn.add(fileEntry, "", RDFFormat.TURTLE, new Resource[] {}); } } logger.info("Loading turtle files finished in " + (System.currentTimeMillis() - start) + " ms"); } public void writeTriplesAsTurtle(OutputStream output, Map<String, String> prefixes) { try { RepositoryResult<Statement> statements = rep.getConnection().getStatements(null, null, null, true); Model model = Iterations.addAll(statements, new LinkedHashModel()); for (String key : prefixes.keySet()) { model.setNamespace(key, prefixes.get(key)); } Rio.write(model, output, RDFFormat.TURTLE); } catch (RepositoryException e) { e.printStackTrace(); throw new SparqlTutorialException(e); } catch (RDFHandlerException e) { e.printStackTrace(); throw new SparqlTutorialException(e); } } public void clearData() { try { RepositoryResult<Statement> statements = rep.getConnection().getStatements(null, null, null, true); rep.getConnection().remove(statements); } catch (RepositoryException e) { e.printStackTrace(); throw new SparqlTutorialException(e); } } public void testLoadTurtleData(String data) { try { InputStream stream = new ByteArrayInputStream(data.getBytes()); RepositoryResult<Statement> statements = testRepo.getConnection().getStatements(null, null, null, true); testRepo.getConnection().remove(statements); testRepo.getConnection().add(stream, "", RDFFormat.TURTLE, new Resource[] {}); } catch (RepositoryException e) { e.printStackTrace(); throw new SparqlTutorialException(e); } catch (RDFParseException e) { e.printStackTrace(); throw new SparqlTutorialException(e); } catch (IOException e) { e.printStackTrace(); throw new SparqlTutorialException(e); } } public void loadTurtleData(String data) { try { InputStream stream = new ByteArrayInputStream(data.getBytes()); rep.getConnection().add(stream, "", RDFFormat.TURTLE, new Resource[] {}); } catch (RepositoryException e) { e.printStackTrace(); throw new SparqlTutorialException(e); } catch (RDFParseException e) { e.printStackTrace(); throw new SparqlTutorialException(e); } catch (IOException e) { e.printStackTrace(); throw new SparqlTutorialException(e); } } public long countTriplets() { try { Query query = prepareQuery("SELECT (COUNT(*) AS ?no) { ?s ?p ?o }"); TupleQueryResult result = ((TupleQuery) query).evaluate(); long n = Long.valueOf(result.next().getBinding("no").getValue().stringValue()); result.close(); return n; } catch (NumberFormatException e) { e.printStackTrace(); throw new SparqlTutorialException(e); } catch (QueryEvaluationException e) { e.printStackTrace(); throw new SparqlTutorialException(e); } } public boolean isDataLoadAllowed() { return rep.getDataDir() == null; } @Override public void afterPropertiesSet() throws Exception { conn = rep.getConnection(); } }