Repository: incubator-rya Updated Branches: refs/heads/master dc238970b -> 8f48c2494
Closes #287. Updating the ExecuteSparqlQuery command to return BindingSets Project: http://git-wip-us.apache.org/repos/asf/incubator-rya/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-rya/commit/8f48c249 Tree: http://git-wip-us.apache.org/repos/asf/incubator-rya/tree/8f48c249 Diff: http://git-wip-us.apache.org/repos/asf/incubator-rya/diff/8f48c249 Branch: refs/heads/master Commit: 8f48c2494b1dacfb7e77a1b2281695a1d4aa1711 Parents: dc23897 Author: Andrew Smith <[email protected]> Authored: Fri Apr 6 16:01:43 2018 -0400 Committer: Valiyil <[email protected]> Committed: Mon Apr 16 14:55:55 2018 -0400 ---------------------------------------------------------------------- .../rya/api/client/ExecuteSparqlQuery.java | 16 ++- .../accumulo/AccumuloExecuteSparqlQuery.java | 108 ++++++------------- .../client/mongo/MongoExecuteSparqlQuery.java | 87 ++++----------- .../client/mongo/MongoExecuteSparqlQueryIT.java | 59 ++++++---- .../java/org/apache/rya/shell/RyaCommands.java | 55 +++++++++- .../org/apache/rya/shell/util/SparqlPrompt.java | 31 ++++++ .../org/apache/rya/shell/MongoRyaShellIT.java | 54 ++++++++++ .../org/apache/rya/shell/RyaCommandsTest.java | 18 ++-- 8 files changed, 253 insertions(+), 175 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/8f48c249/common/rya.api/src/main/java/org/apache/rya/api/client/ExecuteSparqlQuery.java ---------------------------------------------------------------------- diff --git a/common/rya.api/src/main/java/org/apache/rya/api/client/ExecuteSparqlQuery.java b/common/rya.api/src/main/java/org/apache/rya/api/client/ExecuteSparqlQuery.java index 817b752..082beb1 100644 --- a/common/rya.api/src/main/java/org/apache/rya/api/client/ExecuteSparqlQuery.java +++ b/common/rya.api/src/main/java/org/apache/rya/api/client/ExecuteSparqlQuery.java @@ -18,6 +18,11 @@ */ package org.apache.rya.api.client; +import java.io.Closeable; + +import org.openrdf.query.BindingSet; +import org.openrdf.query.TupleQueryResult; + import edu.umd.cs.findbugs.annotations.DefaultAnnotation; import edu.umd.cs.findbugs.annotations.NonNull; @@ -25,15 +30,16 @@ import edu.umd.cs.findbugs.annotations.NonNull; * Loads a SPARQL Query and executes the query against an instance of Rya. */ @DefaultAnnotation(NonNull.class) -public interface ExecuteSparqlQuery { +public interface ExecuteSparqlQuery extends Closeable { + /** - * Loads a SPARQL Query and executes the query against an instance of Rya. + * Executes a SPARQL Query against an instance of Rya. * * @param ryaInstanceName - The name of the Rya instance the query will be executed against. (not null) - * @param sparqlQuery - A single SPARQL Query. (not null) - * @return A user-friendly String representation of the query results. + * @param sparqlQuery - A SPARQL Query. (not null) + * @return A {@link TupleQueryResult} of the resulting {@link BindingSet}s. * @throws InstanceDoesNotExistException No instance of Rya exists for the provided name. * @throws RyaClientException Something caused the command to fail. */ - public String executeSparqlQuery(String ryaInstanceName, String sparqlQuery) throws InstanceDoesNotExistException, RyaClientException; + public TupleQueryResult executeSparqlQuery(String ryaInstanceName, String sparqlQuery) throws InstanceDoesNotExistException, RyaClientException; } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/8f48c249/extras/indexing/src/main/java/org/apache/rya/api/client/accumulo/AccumuloExecuteSparqlQuery.java ---------------------------------------------------------------------- diff --git a/extras/indexing/src/main/java/org/apache/rya/api/client/accumulo/AccumuloExecuteSparqlQuery.java b/extras/indexing/src/main/java/org/apache/rya/api/client/accumulo/AccumuloExecuteSparqlQuery.java index f3e50d0..e9e2cbe 100644 --- a/extras/indexing/src/main/java/org/apache/rya/api/client/accumulo/AccumuloExecuteSparqlQuery.java +++ b/extras/indexing/src/main/java/org/apache/rya/api/client/accumulo/AccumuloExecuteSparqlQuery.java @@ -20,10 +20,7 @@ package org.apache.rya.api.client.accumulo; import static java.util.Objects.requireNonNull; -import java.io.ByteArrayOutputStream; -import java.io.OutputStream; -import java.nio.charset.StandardCharsets; -import java.text.DecimalFormat; +import java.io.IOException; import org.apache.accumulo.core.client.AccumuloException; import org.apache.accumulo.core.client.AccumuloSecurityException; @@ -37,13 +34,11 @@ import org.apache.rya.api.client.RyaClientException; import org.apache.rya.api.persist.RyaDAOException; import org.apache.rya.rdftriplestore.inference.InferenceEngineException; import org.apache.rya.sail.config.RyaSailFactory; -import org.openrdf.query.BindingSet; import org.openrdf.query.MalformedQueryException; import org.openrdf.query.QueryEvaluationException; import org.openrdf.query.QueryLanguage; import org.openrdf.query.TupleQuery; -import org.openrdf.query.TupleQueryResultHandlerException; -import org.openrdf.query.resultio.text.csv.SPARQLResultsCSVWriter; +import org.openrdf.query.TupleQueryResult; import org.openrdf.repository.RepositoryException; import org.openrdf.repository.sail.SailRepository; import org.openrdf.repository.sail.SailRepositoryConnection; @@ -62,6 +57,10 @@ public class AccumuloExecuteSparqlQuery extends AccumuloCommand implements Execu private final InstanceExists instanceExists; + private Sail sail = null; + private SailRepository sailRepo = null; + private SailRepositoryConnection sailRepoConn = null; + /** * Constructs an instance of {@link AccumuloExecuteSparqlQuery}. * @@ -77,7 +76,7 @@ public class AccumuloExecuteSparqlQuery extends AccumuloCommand implements Execu @Override - public String executeSparqlQuery(final String ryaInstanceName, final String sparqlQuery) + public TupleQueryResult executeSparqlQuery(final String ryaInstanceName, final String sparqlQuery) throws InstanceDoesNotExistException, RyaClientException { requireNonNull(ryaInstanceName); requireNonNull(sparqlQuery); @@ -87,11 +86,6 @@ public class AccumuloExecuteSparqlQuery extends AccumuloCommand implements Execu throw new InstanceDoesNotExistException(String.format("There is no Rya instance named '%s'.", ryaInstanceName)); } - - Sail sail = null; - SailRepository sailRepo = null; - SailRepositoryConnection sailRepoConn = null; - try { // Get a Sail object that is connected to the Rya instance. final AccumuloRdfConfiguration ryaConf = getAccumuloConnectionDetails().buildAccumuloRdfConfiguration(ryaInstanceName); @@ -99,83 +93,43 @@ public class AccumuloExecuteSparqlQuery extends AccumuloCommand implements Execu sailRepo = new SailRepository(sail); sailRepoConn = sailRepo.getConnection(); - // Execute the query. - final long start = System.currentTimeMillis(); + // Execute the query. final TupleQuery tupleQuery = sailRepoConn.prepareTupleQuery(QueryLanguage.SPARQL, sparqlQuery); - final ByteArrayOutputStream baos = new ByteArrayOutputStream(); - final CountingSPARQLResultsCSVWriter handler = new CountingSPARQLResultsCSVWriter(baos); - tupleQuery.evaluate(handler); - final StringBuilder sb = new StringBuilder(); - - final String newline = "\n"; - sb.append("Query Result:").append(newline); - sb.append(new String(baos.toByteArray(), StandardCharsets.UTF_8)); - - final String seconds = new DecimalFormat("0.0##").format((System.currentTimeMillis() - start) / 1000.0); - sb.append("Retrieved ").append(handler.getCount()).append(" results in ").append(seconds).append(" seconds."); - - return sb.toString(); - + return tupleQuery.evaluate(); } catch (final SailException | AccumuloException | AccumuloSecurityException | RyaDAOException | InferenceEngineException e) { throw new RyaClientException("A problem connecting to the Rya instance named '" + ryaInstanceName + "' has caused the query to fail.", e); } catch (final MalformedQueryException e) { throw new RyaClientException("There was a problem parsing the supplied query.", e); - } catch (final QueryEvaluationException | TupleQueryResultHandlerException e) { + } catch (final QueryEvaluationException e) { throw new RyaClientException("There was a problem evaluating the supplied query.", e); } catch (final RepositoryException e) { throw new RyaClientException("There was a problem executing the query against the Rya instance named " + ryaInstanceName + ".", e); - } finally { - // Shut it all down. - if(sailRepoConn != null) { - try { - sailRepoConn.close(); - } catch (final RepositoryException e) { - log.warn("Couldn't close the SailRepoConnection that is attached to the Rya instance.", e); - } - } - if(sailRepo != null) { - try { - sailRepo.shutDown(); - } catch (final RepositoryException e) { - log.warn("Couldn't shut down the SailRepository that is attached to the Rya instance.", e); - } - } - if(sail != null) { - try { - sail.shutDown(); - } catch (final SailException e) { - log.warn("Couldn't shut down the Sail that is attached to the Rya instance.", e); - } - } } } - /** - * Subclasses {@link SPARQLResultsCSVWriter} to keep track of the total count of handled {@link BindingSet} objects. - */ - private static class CountingSPARQLResultsCSVWriter extends SPARQLResultsCSVWriter { - - private int count = 0; - - /** - * @param out - The OutputStream for results to be written to. - */ - public CountingSPARQLResultsCSVWriter(final OutputStream out) { - super(out); + @Override + public void close() throws IOException { + // Shut it all down. + if(sailRepoConn != null) { + try { + sailRepoConn.close(); + } catch (final RepositoryException e) { + log.warn("Couldn't close the SailRepoConnection that is attached to the Rya instance.", e); + } } - @Override - public void handleSolution(final BindingSet bindingSet) throws TupleQueryResultHandlerException { - super.handleSolution(bindingSet); - count++; + if(sailRepo != null) { + try { + sailRepo.shutDown(); + } catch (final RepositoryException e) { + log.warn("Couldn't shut down the SailRepository that is attached to the Rya instance.", e); + } } - - /** - * - * @return The number of BindingSets that were handled by {@link #handleSolution(BindingSet)}. - */ - public int getCount() { - return count; + if(sail != null) { + try { + sail.shutDown(); + } catch (final SailException e) { + log.warn("Couldn't shut down the Sail that is attached to the Rya instance.", e); + } } } - } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/8f48c249/extras/indexing/src/main/java/org/apache/rya/api/client/mongo/MongoExecuteSparqlQuery.java ---------------------------------------------------------------------- diff --git a/extras/indexing/src/main/java/org/apache/rya/api/client/mongo/MongoExecuteSparqlQuery.java b/extras/indexing/src/main/java/org/apache/rya/api/client/mongo/MongoExecuteSparqlQuery.java index d3b7bcb..7ce396e 100644 --- a/extras/indexing/src/main/java/org/apache/rya/api/client/mongo/MongoExecuteSparqlQuery.java +++ b/extras/indexing/src/main/java/org/apache/rya/api/client/mongo/MongoExecuteSparqlQuery.java @@ -20,10 +20,7 @@ package org.apache.rya.api.client.mongo; import static java.util.Objects.requireNonNull; -import java.io.ByteArrayOutputStream; -import java.io.OutputStream; -import java.nio.charset.StandardCharsets; -import java.text.DecimalFormat; +import java.io.IOException; import org.apache.accumulo.core.client.AccumuloException; import org.apache.accumulo.core.client.AccumuloSecurityException; @@ -35,13 +32,11 @@ import org.apache.rya.api.persist.RyaDAOException; import org.apache.rya.mongodb.MongoDBRdfConfiguration; import org.apache.rya.rdftriplestore.inference.InferenceEngineException; import org.apache.rya.sail.config.RyaSailFactory; -import org.openrdf.query.BindingSet; import org.openrdf.query.MalformedQueryException; import org.openrdf.query.QueryEvaluationException; import org.openrdf.query.QueryLanguage; import org.openrdf.query.TupleQuery; -import org.openrdf.query.TupleQueryResultHandlerException; -import org.openrdf.query.resultio.text.csv.SPARQLResultsCSVWriter; +import org.openrdf.query.TupleQueryResult; import org.openrdf.repository.RepositoryException; import org.openrdf.repository.sail.SailRepository; import org.openrdf.repository.sail.SailRepositoryConnection; @@ -62,6 +57,8 @@ public class MongoExecuteSparqlQuery implements ExecuteSparqlQuery { private final MongoConnectionDetails connectionDetails; private final InstanceExists instanceExists; + private Sail sail = null; + private SailRepositoryConnection sailRepoConn = null; /** * Constructs an instance of {@link MongoExecuteSparqlQuery}. @@ -77,7 +74,7 @@ public class MongoExecuteSparqlQuery implements ExecuteSparqlQuery { } @Override - public String executeSparqlQuery(final String ryaInstanceName, final String sparqlQuery) throws InstanceDoesNotExistException, RyaClientException { + public TupleQueryResult executeSparqlQuery(final String ryaInstanceName, final String sparqlQuery) throws InstanceDoesNotExistException, RyaClientException { requireNonNull(ryaInstanceName); requireNonNull(sparqlQuery); @@ -86,8 +83,6 @@ public class MongoExecuteSparqlQuery implements ExecuteSparqlQuery { throw new InstanceDoesNotExistException(String.format("There is no Rya instance named '%s'.", ryaInstanceName)); } - Sail sail = null; - SailRepositoryConnection sailRepoConn = null; try { // Get a Sail object that is connected to the Rya instance. final MongoDBRdfConfiguration ryaConf = connectionDetails.build(ryaInstanceName); @@ -97,71 +92,31 @@ public class MongoExecuteSparqlQuery implements ExecuteSparqlQuery { sailRepoConn = sailRepo.getConnection(); // Execute the query. - final long start = System.currentTimeMillis(); final TupleQuery tupleQuery = sailRepoConn.prepareTupleQuery(QueryLanguage.SPARQL, sparqlQuery); - final ByteArrayOutputStream baos = new ByteArrayOutputStream(); - final CountingSPARQLResultsCSVWriter handler = new CountingSPARQLResultsCSVWriter(baos); - tupleQuery.evaluate(handler); - final long end = System.currentTimeMillis(); - - // Format and return the result of the query. - final String queryResult = new String(baos.toByteArray(), StandardCharsets.UTF_8); - final String queryDuration = new DecimalFormat("0.0##").format((end - start) / 1000.0); - - return "Query Result:\n" + - queryResult + - "Retrieved " + handler.getCount() + " results in " + queryDuration + " seconds."; - + return tupleQuery.evaluate(); } catch (SailException | RyaDAOException | InferenceEngineException | AccumuloException | AccumuloSecurityException e) { throw new RyaClientException("Could not create the Sail object used to query the RYA instance.", e); - } catch (final MalformedQueryException | QueryEvaluationException | TupleQueryResultHandlerException | RepositoryException e) { + } catch (final MalformedQueryException | QueryEvaluationException | RepositoryException e) { throw new RyaClientException("Could not execute the SPARQL query.", e); - } finally { - // Close the resources that were opened. - if(sailRepoConn != null) { - try { - sailRepoConn.close(); - } catch (final RepositoryException e) { - log.error("Couldn't close the SailRepositoryConnection object.", e); - } - } - - if(sail != null) { - try { - sail.shutDown(); - } catch (final SailException e) { - log.error("Couldn't close the Sail object.", e); - } - } } } - /** - * Subclasses {@link SPARQLResultsCSVWriter} to keep track of the total count of handled {@link BindingSet} objects. - */ - private static class CountingSPARQLResultsCSVWriter extends SPARQLResultsCSVWriter { - - private int count = 0; - - /** - * @param out - The OutputStream for results to be written to. - */ - public CountingSPARQLResultsCSVWriter(final OutputStream out) { - super(out); - } - - @Override - public void handleSolution(final BindingSet bindingSet) throws TupleQueryResultHandlerException { - super.handleSolution(bindingSet); - count++; + @Override + public void close() throws IOException { + if(sailRepoConn != null) { + try { + sailRepoConn.close(); + } catch (final RepositoryException e) { + log.error("Couldn't close the SailRepositoryConnection object.", e); + } } - /** - * - * @return The number of BindingSets that were handled by {@link #handleSolution(BindingSet)}. - */ - public int getCount() { - return count; + if(sail != null) { + try { + sail.shutDown(); + } catch (final SailException e) { + log.error("Couldn't close the Sail object.", e); + } } } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/8f48c249/extras/indexing/src/test/java/org/apache/rya/api/client/mongo/MongoExecuteSparqlQueryIT.java ---------------------------------------------------------------------- diff --git a/extras/indexing/src/test/java/org/apache/rya/api/client/mongo/MongoExecuteSparqlQueryIT.java b/extras/indexing/src/test/java/org/apache/rya/api/client/mongo/MongoExecuteSparqlQueryIT.java index 5c14112..a1fee6f 100644 --- a/extras/indexing/src/test/java/org/apache/rya/api/client/mongo/MongoExecuteSparqlQueryIT.java +++ b/extras/indexing/src/test/java/org/apache/rya/api/client/mongo/MongoExecuteSparqlQueryIT.java @@ -18,23 +18,22 @@ */ package org.apache.rya.api.client.mongo; -import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertEquals; import java.util.ArrayList; import java.util.List; import org.apache.rya.api.client.ExecuteSparqlQuery; -import org.apache.rya.api.client.Install.DuplicateInstanceNameException; import org.apache.rya.api.client.Install.InstallConfiguration; import org.apache.rya.api.client.RyaClient; -import org.apache.rya.api.client.RyaClientException; import org.apache.rya.mongodb.MongoITBase; import org.junit.Test; import org.openrdf.model.Statement; import org.openrdf.model.ValueFactory; import org.openrdf.model.impl.ValueFactoryImpl; - -import com.mongodb.MongoException; +import org.openrdf.query.BindingSet; +import org.openrdf.query.TupleQueryResult; +import org.openrdf.query.impl.MapBindingSet; /** * Integration tests the methods of {@link }. @@ -42,7 +41,7 @@ import com.mongodb.MongoException; public class MongoExecuteSparqlQueryIT extends MongoITBase { @Test - public void ExecuteSparqlQuery_exec() throws MongoException, DuplicateInstanceNameException, RyaClientException { + public void ExecuteSparqlQuery_exec() throws Exception { // Install an instance of Rya. final MongoConnectionDetails connectionDetails = getConnectionDetails(); final RyaClient ryaClient = MongoRyaClientFactory.build(connectionDetails, getMongoClient()); @@ -64,20 +63,18 @@ public class MongoExecuteSparqlQueryIT extends MongoITBase { // Execute the SPARQL against the Rya instance. final ExecuteSparqlQuery executeSparql = ryaClient.getExecuteSparqlQuery(); final String sparql = "SELECT * where { ?a ?b ?c }"; - final String results = executeSparql.executeSparqlQuery(conf.getRyaInstanceName(), sparql); - - // Show the result matches what is expected. - assertTrue("result has header.", results.startsWith("Query Result:")); - assertTrue("result has column headings.", results.contains("a,b,c")); - assertTrue("result has footer.", results.contains("Retrieved 3 results in")); - for (final Statement expect : statements) { - assertTrue("All results should contain expected subjects:", - results.contains(expect.getSubject().stringValue())); - assertTrue("All results should contain expected predicates:", - results.contains(expect.getPredicate().stringValue())); - assertTrue("All results should contain expected objects:", - results.contains(expect.getObject().stringValue())); + final TupleQueryResult results = executeSparql.executeSparqlQuery(conf.getRyaInstanceName(), sparql); + + final List<BindingSet> expected = makeExpectedResults(); + final List<BindingSet> actual = new ArrayList<>(); + + while(results.hasNext()) { + actual.add(results.next()); } + results.close(); + executeSparql.close(); + + assertEquals(expected, actual); } /** @@ -96,6 +93,30 @@ public class MongoExecuteSparqlQueryIT extends MongoITBase { return loadMe; } + private List<BindingSet> makeExpectedResults() { + final List<BindingSet> expected = new ArrayList<>(); + final ValueFactory vf = new ValueFactoryImpl(); + MapBindingSet bs = new MapBindingSet(); + bs.addBinding("a", vf.createURI("http://example#alice")); + bs.addBinding("b", vf.createURI("http://example#talksTo")); + bs.addBinding("c", vf.createURI("http://example#bob")); + expected.add(bs); + + bs = new MapBindingSet(); + bs.addBinding("a", vf.createURI("http://example#bob")); + bs.addBinding("b", vf.createURI("http://example#talksTo")); + bs.addBinding("c", vf.createURI("http://example#charlie")); + expected.add(bs); + + bs = new MapBindingSet(); + bs.addBinding("a", vf.createURI("http://example#charlie")); + bs.addBinding("b", vf.createURI("http://example#likes")); + bs.addBinding("c", vf.createURI("http://example#icecream")); + expected.add(bs); + + return expected; + } + private MongoConnectionDetails getConnectionDetails() { final java.util.Optional<char[]> password = conf.getMongoPassword() != null ? java.util.Optional.of(conf.getMongoPassword().toCharArray()) : http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/8f48c249/extras/shell/src/main/java/org/apache/rya/shell/RyaCommands.java ---------------------------------------------------------------------- diff --git a/extras/shell/src/main/java/org/apache/rya/shell/RyaCommands.java b/extras/shell/src/main/java/org/apache/rya/shell/RyaCommands.java index a650400..1d53348 100644 --- a/extras/shell/src/main/java/org/apache/rya/shell/RyaCommands.java +++ b/extras/shell/src/main/java/org/apache/rya/shell/RyaCommands.java @@ -27,14 +27,19 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.text.DecimalFormat; +import java.util.ArrayList; +import java.util.List; import java.util.Objects; import org.apache.commons.io.FilenameUtils; +import org.apache.rya.api.client.ExecuteSparqlQuery; import org.apache.rya.api.client.RyaClient; import org.apache.rya.api.client.RyaClientException; import org.apache.rya.shell.SharedShellState.ShellState; import org.apache.rya.shell.util.ConsolePrinter; import org.apache.rya.shell.util.SparqlPrompt; +import org.openrdf.query.BindingSet; +import org.openrdf.query.TupleQueryResult; import org.openrdf.rio.RDFFormat; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -47,6 +52,8 @@ import org.springframework.stereotype.Component; import com.google.common.base.Optional; +import joptsimple.internal.Strings; + /** * Rya Shell commands that have to do with common tasks (loading and querying data) */ @@ -150,6 +157,7 @@ public class RyaCommands implements CommandMarker { final RyaClient commands = shellState.getConnectedCommands().get(); final Optional<String> ryaInstanceName = shellState.getRyaInstanceName(); + final ExecuteSparqlQuery queryCommand = commands.getExecuteSparqlQuery(); try { // file option specified String sparqlQuery; @@ -169,10 +177,55 @@ public class RyaCommands implements CommandMarker { consolePrinter.println("Executing Query..."); consolePrinter.flush(); - return commands.getExecuteSparqlQuery().executeSparqlQuery(ryaInstanceName.get(), sparqlQuery); + final TupleQueryResult rezIter = queryCommand.executeSparqlQuery(ryaInstanceName.get(), sparqlQuery); + + final List<String> bindings = new ArrayList<>(); + if(rezIter.hasNext()) { + consolePrinter.println("Query Results:"); + final BindingSet bs = rezIter.next(); + for(final String name : rezIter.next().getBindingNames()) { + bindings.add(name); + } + consolePrinter.println(Strings.join(bindings, ",")); + consolePrinter.println(formatLine(bs, bindings)); + } else { + consolePrinter.println("No Results Found."); + } + + int count = 0; + while(rezIter.hasNext()) { + final BindingSet bs = rezIter.next(); + consolePrinter.println(formatLine(bs, bindings)); + count++; + if(count == 20) { + final Optional<String> rez = sparqlPrompt.getSparqlWithResults(); + if(rez.isPresent()) { + break; + } + } + } + rezIter.close(); + return "Done."; } catch (final RyaClientException | IOException e) { log.error("Error", e); throw new RuntimeException("Can not execute the SPARQL Query. Reason: " + e.getMessage(), e); + } catch(final Exception e) { + log.error("Failed to close the results iterator.", e); + return ""; + } finally { + try { + queryCommand.close(); + } catch (final IOException e) { + log.error("Failed to close the sail resources used.", e); + } + } + } + + private String formatLine(final BindingSet bs, final List<String> bindings) { + final List<String> bindingValues = new ArrayList<>(); + for(final String bindingName : bindings) { + bindingValues.add(bs.getBinding(bindingName).getValue().toString()); } + return Strings.join(bindingValues, ","); } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/8f48c249/extras/shell/src/main/java/org/apache/rya/shell/util/SparqlPrompt.java ---------------------------------------------------------------------- diff --git a/extras/shell/src/main/java/org/apache/rya/shell/util/SparqlPrompt.java b/extras/shell/src/main/java/org/apache/rya/shell/util/SparqlPrompt.java index 2574eea..9fb364e 100644 --- a/extras/shell/src/main/java/org/apache/rya/shell/util/SparqlPrompt.java +++ b/extras/shell/src/main/java/org/apache/rya/shell/util/SparqlPrompt.java @@ -41,6 +41,14 @@ public interface SparqlPrompt { public Optional<String> getSparql() throws IOException; /** + * Prompt the user for a SPARQL query, wait for their input, and then get the value they entered. + * + * @return The user entered SPARQL query, or an empty string if the user aborts. + * @throws IOException There was a problem reading the user's input. + */ + public Optional<String> getSparqlWithResults() throws IOException; + + /** * Prompts a user for a SPARQL query using a JLine {@link ConsoleReader}. */ @DefaultAnnotation(NonNull.class) @@ -48,6 +56,8 @@ public interface SparqlPrompt { private final String EXECUTE_COMMAND = "\\e"; private final String CLEAR_COMMAND = "\\c"; + private final String NEXT_RESULTS_COMMAND = "ENTER"; + private final String STOP_COMMAND = "\\s"; @Override public Optional<String> getSparql() throws IOException { @@ -77,6 +87,27 @@ public interface SparqlPrompt { reader.setCopyPasteDetection(false); // restore tab completion } } + + @Override + public Optional<String> getSparqlWithResults() throws IOException { + final ConsoleReader reader = getReader(); + reader.setCopyPasteDetection(true); // disable tab completion from activating + reader.setHistoryEnabled(false); // don't store SPARQL fragments in the command history + try { + reader.println("To see more results press [Enter]."); + reader.println("Type '" + STOP_COMMAND + "' to stop showing results."); + reader.flush(); + + final String line = reader.readLine("> "); + if(line.endsWith(STOP_COMMAND)) { + return Optional.of(STOP_COMMAND); + } + return Optional.absent(); + } finally { + reader.setHistoryEnabled(true); // restore the ConsoleReader's settings + reader.setCopyPasteDetection(false); // restore tab completion + } + } } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/8f48c249/extras/shell/src/test/java/org/apache/rya/shell/MongoRyaShellIT.java ---------------------------------------------------------------------- diff --git a/extras/shell/src/test/java/org/apache/rya/shell/MongoRyaShellIT.java b/extras/shell/src/test/java/org/apache/rya/shell/MongoRyaShellIT.java index 79fe95d..bf44db4 100644 --- a/extras/shell/src/test/java/org/apache/rya/shell/MongoRyaShellIT.java +++ b/extras/shell/src/test/java/org/apache/rya/shell/MongoRyaShellIT.java @@ -21,21 +21,30 @@ package org.apache.rya.shell; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.io.IOException; +import java.util.Optional; import org.apache.rya.api.client.Install.InstallConfiguration; +import org.apache.rya.api.client.RyaClient; +import org.apache.rya.api.client.mongo.MongoConnectionDetails; +import org.apache.rya.api.client.mongo.MongoRyaClientFactory; import org.apache.rya.shell.SharedShellState.ConnectionState; import org.apache.rya.shell.SharedShellState.ShellState; +import org.apache.rya.shell.util.ConsolePrinter; import org.apache.rya.shell.util.InstallPrompt; import org.apache.rya.shell.util.PasswordPrompt; +import org.apache.rya.shell.util.SparqlPrompt; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.shell.Bootstrap; import org.springframework.shell.core.CommandResult; import org.springframework.shell.core.JLineShellComponent; +import com.mongodb.MongoClient; + /** * Integration tests the functions of the Mongo Rya Shell. */ @@ -191,4 +200,49 @@ public class MongoRyaShellIT extends RyaShellMongoITBase { } // TODO the rest of them? + + + @Test + public void blah() throws Exception { + final MongoConnectionDetails details = + new MongoConnectionDetails( + "localhost", + 27017, + Optional.empty(), + Optional.empty()); + final RyaClient client = MongoRyaClientFactory.build(details, new MongoClient("localhost", 27017)); + final SharedShellState state = new SharedShellState(); + state.connectedToMongo(details, client); + state.connectedToInstance("rya_"); + final ShellState shell = state.getShellState(); + final SparqlPrompt sparqlPrompt = mock(SparqlPrompt.class); + when(sparqlPrompt.getSparql()).thenReturn( + com.google.common.base.Optional.<String>of("SELECT * WHERE { ?a ?b ?c }")); + final RyaCommands cmnds = new RyaCommands + (state, sparqlPrompt, systemPrinter); + cmnds.sparqlQuery(null); + } + + private static final ConsolePrinter systemPrinter = new ConsolePrinter() { + + @Override + public void print(final CharSequence cs) throws IOException { + System.out.print(cs); + } + + @Override + public void println(final CharSequence cs) throws IOException { + System.out.println(cs); + } + + @Override + public void println() throws IOException { + System.out.println(); + } + + @Override + public void flush() throws IOException { + System.out.flush(); + } + }; } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/8f48c249/extras/shell/src/test/java/org/apache/rya/shell/RyaCommandsTest.java ---------------------------------------------------------------------- diff --git a/extras/shell/src/test/java/org/apache/rya/shell/RyaCommandsTest.java b/extras/shell/src/test/java/org/apache/rya/shell/RyaCommandsTest.java index 21384ea..d08b0bd 100644 --- a/extras/shell/src/test/java/org/apache/rya/shell/RyaCommandsTest.java +++ b/extras/shell/src/test/java/org/apache/rya/shell/RyaCommandsTest.java @@ -38,6 +38,7 @@ import org.apache.rya.api.client.accumulo.AccumuloConnectionDetails; import org.apache.rya.shell.util.ConsolePrinter; import org.apache.rya.shell.util.SparqlPrompt; import org.junit.Test; +import org.openrdf.query.TupleQueryResult; import org.openrdf.rio.RDFFormat; import com.google.common.base.Optional; @@ -102,7 +103,7 @@ public class RyaCommandsTest { // Verify the values that were provided to the command were passed through to LoadStatementsFile // using a user rooted filename. - String rootedFile = System.getProperty("user.home") + "/statements.nt"; + final String rootedFile = System.getProperty("user.home") + "/statements.nt"; verify(mockLoadStatementsFile).loadStatements(instanceName, Paths.get(rootedFile), RDFFormat.NTRIPLES); // Verify a message is returned that explains what was created. @@ -197,10 +198,10 @@ public class RyaCommandsTest { final String instanceName = "unitTest"; final String queryFile = "src/test/resources/Query1.sparql"; final String queryContent = FileUtils.readFileToString(new File(queryFile), StandardCharsets.UTF_8); - final String expectedMessage = "MockAnswer"; + final TupleQueryResult expectedResult = mock(TupleQueryResult.class); final ExecuteSparqlQuery mockExecuteSparqlQuery = mock(ExecuteSparqlQuery.class); - when(mockExecuteSparqlQuery.executeSparqlQuery(instanceName, queryContent)).thenReturn(expectedMessage); + when(mockExecuteSparqlQuery.executeSparqlQuery(instanceName, queryContent)).thenReturn(expectedResult); final RyaClient mockCommands = mock(RyaClient.class); when(mockCommands.getExecuteSparqlQuery()).thenReturn(mockExecuteSparqlQuery); @@ -221,7 +222,7 @@ public class RyaCommandsTest { // Verify the values that were provided to the command were passed through to LoadStatementsFile. verify(mockExecuteSparqlQuery).executeSparqlQuery(instanceName, queryContent); - assertEquals(expectedMessage, message); + assertEquals("Done.", message); // Verify a message is returned that explains what was created. } @@ -252,10 +253,10 @@ public class RyaCommandsTest { final String instanceName = "unitTest"; final String queryContent = "SELECT * WHERE { ?person <http://isA> ?noun }"; final String queryFile = null; - final String expectedMessage = "MockAnswer"; + final TupleQueryResult expectedResult = mock(TupleQueryResult.class); final ExecuteSparqlQuery mockExecuteSparqlQuery = mock(ExecuteSparqlQuery.class); - when(mockExecuteSparqlQuery.executeSparqlQuery(instanceName, queryContent)).thenReturn(expectedMessage); + when(mockExecuteSparqlQuery.executeSparqlQuery(instanceName, queryContent)).thenReturn(expectedResult); final RyaClient mockCommands = mock(RyaClient.class); when(mockCommands.getExecuteSparqlQuery()).thenReturn(mockExecuteSparqlQuery); @@ -277,7 +278,7 @@ public class RyaCommandsTest { // Verify the values that were provided to the command were passed through to LoadStatementsFile. verify(mockExecuteSparqlQuery).executeSparqlQuery(instanceName, queryContent); - assertEquals(expectedMessage, message); + assertEquals("Done.", message); // Verify a message is returned that explains what was created. } @@ -288,7 +289,10 @@ public class RyaCommandsTest { final String queryFile = null; final String expectedMessage = ""; + //since the ExecuteSparqlQuery is closed by the shell, a mock needs to be created + final ExecuteSparqlQuery mockQuery = mock(ExecuteSparqlQuery.class); final RyaClient mockCommands = mock(RyaClient.class); + when(mockCommands.getExecuteSparqlQuery()).thenReturn(mockQuery); final SharedShellState state = new SharedShellState(); state.connectedToAccumulo(mock(AccumuloConnectionDetails.class), mockCommands);
