Added support for queries returning boolean results (i.e. ASK queries)
diff --git a/impl.sparql/src/main/java/org/apache/clerezza/commons/rdf/impl/sparql/SparqlClient.java b/impl.sparql/src/main/java/org/apache/clerezza/commons/rdf/impl/sparql/SparqlClient.java
index 2745a0e..4191748 100644
--- a/impl.sparql/src/main/java/org/apache/clerezza/commons/rdf/impl/sparql/SparqlClient.java
+++ b/impl.sparql/src/main/java/org/apache/clerezza/commons/rdf/impl/sparql/SparqlClient.java
@@ -54,7 +54,11 @@
         this.endpoint = endpoint;
     }
 
-    List<Map<String, RDFTerm>> queryResultSet(final String query) throws IOException {
+    public List<Map<String, RDFTerm>> queryResultSet(final String query) throws IOException {
+        return (List<Map<String, RDFTerm>>) queryResult(query);
+    }
+    
+    public Object queryResult(final String query) throws IOException {
         CloseableHttpClient httpclient = HttpClients.createDefault();
         HttpPost httpPost = new HttpPost(endpoint);
         List<NameValuePair> nvps = new ArrayList<NameValuePair>();
@@ -95,7 +99,7 @@
 
         private String currentBindingName;
         private Map<String, RDFTerm> currentResult = null;
-        private final List<Map<String, RDFTerm>> results = new ArrayList<>();
+        private Object results = null;
         private boolean readingValue;
         private String lang; //the xml:lang attribute of a literal
         private StringWriter valueWriter;
@@ -110,9 +114,13 @@
             return bNodeMap.get(value);
         }
 
-        private List<Map<String, RDFTerm>> getResults() {
+        private Object getResults() {
             return results;
         }
+        
+        private List<Map<String, RDFTerm>> getResultValueMaps() {
+            return (List<Map<String, RDFTerm>>)results;
+        }
 
         enum BindingType {
 
@@ -130,12 +138,24 @@
                 String qName,
                 Attributes atts)
                 throws SAXException {
-            if ("http://www.w3.org/2005/sparql-results#".equals(namespaceURI)) {
-                if ("result".equals(localName)) {
+            if ("http://www.w3.org/2005/sparql-results#".equals(namespaceURI)) {                
+                if ("boolean".equals(localName)) {
+                    if (results != null) {
+                        throw new SAXException("unexpected tag <boolean>");
+                    }
+                    //results will have Boolean value assigned once value is read
+                    readingValue = true;
+                    valueWriter = new StringWriter();
+                } else if ("results".equals(localName)) {
+                    if (results != null) {
+                        throw new SAXException("unexpected tag <result>");
+                    }
+                    results = new ArrayList<Map<String, RDFTerm>>();
+                } else if ("result".equals(localName)) {
                     if (currentResult != null) {
                         throw new SAXException("unexpected tag <result>");
                     }
-                    currentResult = new HashMap<>();
+                    currentResult = new HashMap<String, RDFTerm>();
                 } else if ("binding".equals(localName)) {
                     if (currentResult == null) {
                         throw new SAXException("unexpected tag <binding>");
@@ -170,13 +190,17 @@
                 throws SAXException {
             if ("http://www.w3.org/2005/sparql-results#".equals(namespaceURI)) {
                 if ("result".equals(localName)) {
-                    results.add(currentResult);
+                    ((List<Map<String, RDFTerm>>)results).add(currentResult);
                     currentResult = null;
                 } else if ("binding".equals(localName)) {
                     if (currentBindingName == null) {
                         throw new SAXException("unexpected tag </binding>");
                     }
                     currentBindingName = null;
+                } else if ("boolean".equals(localName)) {
+                    results = new Boolean(valueWriter.toString());
+                    valueWriter = null;
+                    readingValue = false;
                 } else {
                     try {
                         BindingType b = BindingType.valueOf(localName);
@@ -213,6 +237,11 @@
                                     public Language getLanguage() {
                                         return language;
                                     }
+                                    
+                                    @Override
+                                    public String toString() {
+                                        return "\""+getLexicalForm()+"\"@"+getLanguage();
+                                    }
                                 };
                                 break;
                         }
diff --git a/impl.sparql/src/test/java/org/apache/clerezza/commons/rdf/impl/sparql/BNodeTest.java b/impl.sparql/src/test/java/org/apache/clerezza/commons/rdf/impl/sparql/BNodeTest.java
index e1fda73..168ef74 100644
--- a/impl.sparql/src/test/java/org/apache/clerezza/commons/rdf/impl/sparql/BNodeTest.java
+++ b/impl.sparql/src/test/java/org/apache/clerezza/commons/rdf/impl/sparql/BNodeTest.java
@@ -66,7 +66,7 @@
     @Test
     public void graphSize() {
         final Graph graph = new SparqlGraph("http://localhost:" + serverPort + "/ds/query");
-        Assert.assertEquals("Graph not of the exepected size", 3, graph.size());
+        Assert.assertEquals("Graph not of the expected size", 3, graph.size());
     }
 
     /* Filtering with a Bode that cannot be in graph
diff --git a/impl.sparql/src/test/java/org/apache/clerezza/commons/rdf/impl/sparql/SparqlClientTest.java b/impl.sparql/src/test/java/org/apache/clerezza/commons/rdf/impl/sparql/SparqlClientTest.java
new file mode 100644
index 0000000..fcda4de
--- /dev/null
+++ b/impl.sparql/src/test/java/org/apache/clerezza/commons/rdf/impl/sparql/SparqlClientTest.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2015 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.clerezza.commons.rdf.impl.sparql;
+
+import com.hp.hpl.jena.query.DatasetAccessor;
+import com.hp.hpl.jena.query.DatasetAccessorFactory;
+import java.io.IOException;
+import java.net.ServerSocket;
+import org.apache.jena.fuseki.EmbeddedFusekiServer;
+import com.hp.hpl.jena.rdf.model.Model;
+import com.hp.hpl.jena.rdf.model.ModelFactory;
+import java.io.InputStream;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import org.apache.clerezza.commons.rdf.BlankNode;
+import org.apache.clerezza.commons.rdf.BlankNodeOrIRI;
+import org.apache.clerezza.commons.rdf.Graph;
+import org.apache.clerezza.commons.rdf.IRI;
+import org.apache.clerezza.commons.rdf.RDFTerm;
+import org.apache.clerezza.commons.rdf.Triple;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ *
+ * @author reto
+ */
+public class SparqlClientTest {
+
+    final static int serverPort = findFreePort();
+    static EmbeddedFusekiServer server;
+
+    @BeforeClass
+    public static void prepare() throws IOException {
+        final String serviceURI = "http://localhost:" + serverPort + "/ds/data";
+        final DatasetAccessor accessor = DatasetAccessorFactory.createHTTP(serviceURI);
+        final InputStream in = SparqlClientTest.class.getResourceAsStream("grounded.ttl");
+        final Model m = ModelFactory.createDefaultModel();
+        String base = "http://example.org/";
+        m.read(in, base, "TURTLE");
+        server = EmbeddedFusekiServer.memTDB(serverPort, "/ds");//dataSet.getAbsolutePath());
+        server.start();
+        System.out.println("Started fuseki on port " + serverPort);
+        accessor.putModel(m);
+    }
+
+    @AfterClass
+    public static void cleanup() {
+        server.stop();
+    }
+    
+    @Test
+    public void select() throws IOException {
+        final SparqlClient sparqlClient = new SparqlClient(
+                "http://localhost:" + serverPort + "/ds/query");
+        List<Map<String, RDFTerm>> result = sparqlClient.queryResultSet(
+                "SELECT ?name WHERE { "
+                        + "<http://example.org/#spiderman> "
+                        + "<http://xmlns.com/foaf/0.1/name> ?name}");
+        Assert.assertEquals("There should be two names", 2, result.size());
+    }
+    
+    @Test
+    public void ask() throws IOException {
+        final SparqlClient sparqlClient = new SparqlClient(
+                "http://localhost:" + serverPort + "/ds/query");
+        Object result = sparqlClient.queryResult(
+                "ASK { "
+                        + "<http://example.org/#spiderman> "
+                        + "<http://xmlns.com/foaf/0.1/name> ?name}");
+        Assert.assertEquals("ASK should result to true", Boolean.TRUE, result);
+    }    
+
+    public static int findFreePort() {
+        int port = 0;
+        try (ServerSocket server = new ServerSocket(0);) {
+            port = server.getLocalPort();
+        } catch (Exception e) {
+            throw new RuntimeException("unable to find a free port");
+        }
+        return port;
+    }
+
+}