[Mulgara-svn] r1917 - in trunk/src/jar/querylang/java/org/mulgara/protocol: . http

pag at mulgara.org pag at mulgara.org
Mon Feb 15 19:27:39 UTC 2010


Author: pag
Date: 2010-02-15 11:27:38 -0800 (Mon, 15 Feb 2010)
New Revision: 1917

Modified:
   trunk/src/jar/querylang/java/org/mulgara/protocol/AbstractStreamedAnswer.java
   trunk/src/jar/querylang/java/org/mulgara/protocol/AbstractStreamedXMLAnswer.java
   trunk/src/jar/querylang/java/org/mulgara/protocol/StreamedRdfXmlAnswer.java
   trunk/src/jar/querylang/java/org/mulgara/protocol/StreamedSparqlJSONAnswer.java
   trunk/src/jar/querylang/java/org/mulgara/protocol/StreamedSparqlXMLAnswer.java
   trunk/src/jar/querylang/java/org/mulgara/protocol/StreamedTqlXMLAnswer.java
   trunk/src/jar/querylang/java/org/mulgara/protocol/http/ProtocolServlet.java
Log:
Added method signatures to permit lists of Answers to be streamed, instead of just a single Answer. SPARQL requires these lists to have just one element, but TQL will allow multiple entries. The ProtocolServlet does not yet send multiple Answers to be streamed. Also updated the ProtocolServlet to tell the RdfXmlEmitter to not close an Answer after processing it.

Modified: trunk/src/jar/querylang/java/org/mulgara/protocol/AbstractStreamedAnswer.java
===================================================================
--- trunk/src/jar/querylang/java/org/mulgara/protocol/AbstractStreamedAnswer.java	2010-02-15 19:24:58 UTC (rev 1916)
+++ trunk/src/jar/querylang/java/org/mulgara/protocol/AbstractStreamedAnswer.java	2010-02-15 19:27:38 UTC (rev 1917)
@@ -20,6 +20,8 @@
 import java.io.OutputStream;
 import java.io.OutputStreamWriter;
 import java.nio.charset.Charset;
+import java.util.Collections;
+import java.util.List;
 
 import org.apache.log4j.Logger;
 
@@ -42,14 +44,14 @@
   /** Logger. */
   private final static Logger logger = Logger.getLogger(AbstractStreamedAnswer.class);
 
-  /** The API {@link Answer} to convert to the stream. */
-  protected final Answer answer;
+  /** The API {@link Answer}s to convert to the stream. */
+  protected final List<Answer> answers;
 
-  /** The number of columns in the Answer. */
-  protected final int width;
+  /** The number of columns in the current Answer. */
+  protected int width;
 
-  /** The {@link Variable}s in the Answer. */
-  protected final Variable[] vars;
+  /** The {@link Variable}s in the current Answer. */
+  protected Variable[] vars;
 
   /** The writer used for creating the XML. */
   protected OutputStreamWriter s = null;
@@ -73,16 +75,16 @@
   protected abstract void addBinding(Variable var, Object value) throws TuplesException, IOException;
 
   /** Adds a single result to the stream */
-  protected abstract void addResult() throws TuplesException, IOException;
+  protected abstract void addResult(Answer a) throws TuplesException, IOException;
 
   /** Adds all results to the stream */
-  protected abstract void addResults() throws TuplesException, IOException;
+  protected abstract void addResults(Answer a) throws TuplesException, IOException;
 
   /** Adds a variable in the header to the stream */
   protected abstract void addHeaderVariable(Variable var) throws IOException;
 
   /** Adds the entire header to the stream */
-  protected abstract void addHeader() throws IOException;
+  protected abstract void addHeader(Answer a) throws IOException;
 
   /** Closes the document in the stream */
   protected abstract void addDocFooter() throws IOException;
@@ -97,10 +99,26 @@
    * @param output The stream to write to.
    */
   public AbstractStreamedAnswer(Answer answer, OutputStream output) {
-    this.answer = answer;
+    this(Collections.singletonList(answer), output);
+  }
+
+  /**
+   * Creates the object around the answer and output stream.
+   * @param answer The answer to encode.
+   * @param output The stream to write to.
+   */
+  public AbstractStreamedAnswer(Answer answer, OutputStream output, String charsetName) {
+    this(Collections.singletonList(answer), output, charsetName);
+  }
+
+  /**
+   * Creates the object around the answer and output stream.
+   * @param answer The answer to encode.
+   * @param output The stream to write to.
+   */
+  public AbstractStreamedAnswer(List<Answer> answers, OutputStream output) {
+    this.answers = answers;
     this.output = output;
-    width = (answer != null) ? answer.getNumberOfVariables() : 0;
-    vars = (answer != null) ? answer.getVariables() : null;
   }
 
   /**
@@ -108,8 +126,8 @@
    * @param answer The answer to encode.
    * @param output The stream to write to.
    */
-  public AbstractStreamedAnswer(Answer answer, OutputStream output, String charsetName) {
-    this(answer, output);
+  public AbstractStreamedAnswer(List<Answer> answers, OutputStream output, String charsetName) {
+    this(answers, output);
     try {
       charset = Charset.forName(charsetName);
     } catch (Exception e) {
@@ -134,8 +152,12 @@
    */
   void generate() throws TuplesException, IOException {
     addDocHeader();
-    addHeader();
-    addResults();
+    for (Answer a: answers) {
+      width = (a != null) ? a.getNumberOfVariables() : 0;
+      vars = (a != null) ? a.getVariables() : null;
+      addHeader(a);
+      addResults(a);
+    }
     addDocFooter();
   }
 

Modified: trunk/src/jar/querylang/java/org/mulgara/protocol/AbstractStreamedXMLAnswer.java
===================================================================
--- trunk/src/jar/querylang/java/org/mulgara/protocol/AbstractStreamedXMLAnswer.java	2010-02-15 19:24:58 UTC (rev 1916)
+++ trunk/src/jar/querylang/java/org/mulgara/protocol/AbstractStreamedXMLAnswer.java	2010-02-15 19:27:38 UTC (rev 1917)
@@ -21,6 +21,7 @@
 import java.net.URI;
 import java.nio.charset.Charset;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 import org.jrdf.graph.BlankNode;
@@ -82,6 +83,22 @@
   }
 
   /**
+   * Create an XMLAnswer based on a given {@link Answer}.
+   * @param answers The list of Answers with the data to convert.
+   */
+  public AbstractStreamedXMLAnswer(List<Answer> answers, OutputStream output) {
+    super(answers, output);
+  }
+
+  /**
+   * Create an XMLAnswer based on a given {@link Answer}.
+   * @param answers The list of Answers with the data to convert.
+   */
+  public AbstractStreamedXMLAnswer(List<Answer> answers, OutputStream output, String charsetName) {
+    super(answers, output, charsetName);
+  }
+
+  /**
    * @see org.mulgara.protocol.StreamedXMLAnswer#setCharacterEncoding(java.lang.String)
    */
   public void setCharacterEncoding(String encoding) {
@@ -147,16 +164,18 @@
 
   /**
    * Adds the header to the document data.
+   * @param a The answer to add a header for.
    */
   @Override
-  protected abstract void addHeader() throws IOException;
+  protected abstract void addHeader(Answer a) throws IOException;
 
   /**
    * Adds the results to the document data.
+   * @param a The answer to add the results for.
    * @throws TuplesException Indicates an error accessing the Answer.
    */
   @Override
-  protected abstract void addResults() throws TuplesException, IOException;
+  protected abstract void addResults(Answer a) throws TuplesException, IOException;
 
   /**
    * Adds a variable to the header.
@@ -167,10 +186,11 @@
 
   /**
    * Adds a single result, based on the current result in the {@link #answer}.
+   * @param a The answer to get the result from
    * @throws TuplesException Indicates an error accessing the Answer.
    */
   @Override
-  protected abstract void addResult() throws TuplesException, IOException;
+  protected abstract void addResult(Answer a) throws TuplesException, IOException;
 
   /**
    * Adds a single binding from the current result in the {@link #answer}.

Modified: trunk/src/jar/querylang/java/org/mulgara/protocol/StreamedRdfXmlAnswer.java
===================================================================
--- trunk/src/jar/querylang/java/org/mulgara/protocol/StreamedRdfXmlAnswer.java	2010-02-15 19:24:58 UTC (rev 1916)
+++ trunk/src/jar/querylang/java/org/mulgara/protocol/StreamedRdfXmlAnswer.java	2010-02-15 19:27:38 UTC (rev 1917)
@@ -55,7 +55,7 @@
    */
   public void emit() throws TuplesException, IOException {
     try {
-      RdfXmlEmitter.writeRdfXml(ans, out);
+      RdfXmlEmitter.writeRdfXml(ans, out, true, false);
     } catch (QueryException e) {
       Throwable cause = e.getCause();
       if (cause instanceof TuplesException) throw (TuplesException)cause;

Modified: trunk/src/jar/querylang/java/org/mulgara/protocol/StreamedSparqlJSONAnswer.java
===================================================================
--- trunk/src/jar/querylang/java/org/mulgara/protocol/StreamedSparqlJSONAnswer.java	2010-02-15 19:24:58 UTC (rev 1916)
+++ trunk/src/jar/querylang/java/org/mulgara/protocol/StreamedSparqlJSONAnswer.java	2010-02-15 19:27:38 UTC (rev 1917)
@@ -75,7 +75,7 @@
    * @param output The stream to write to.
    */
   public StreamedSparqlJSONAnswer(boolean result, OutputStream output) {
-    super(null, output);
+    super((Answer)null, output);
     booleanResult = result;
   }
 
@@ -86,7 +86,7 @@
    * @param output The stream to write to.
    */
   public StreamedSparqlJSONAnswer(boolean result, URI metadata, OutputStream output) {
-    super(null, output);
+    super((Answer)null, output);
     booleanResult = result;
     additionalMetadata = metadata;
   }
@@ -121,7 +121,7 @@
    * @param charsetName The name of the character set to use, if not the default of UTF-8.
    */
   public StreamedSparqlJSONAnswer(boolean result, OutputStream output, String charsetName) {
-    super(null, output, charsetName);
+    super((Answer)null, output, charsetName);
     booleanResult = result;
   }
 
@@ -133,7 +133,7 @@
    * @param charsetName The name of the character set to use, if not the default of UTF-8.
    */
   public StreamedSparqlJSONAnswer(boolean result, URI metadata, OutputStream output, String charsetName) {
-    super(null, output, charsetName);
+    super((Answer)null, output, charsetName);
     booleanResult = result;
     additionalMetadata = metadata;
   }
@@ -149,7 +149,7 @@
   }
 
   /** {@inheritDoc} */
-  protected void addHeader() throws IOException {
+  protected void addHeader(Answer answer) throws IOException {
     s.append("\"head\": {");
     boolean wroteVars = false;
     if (answer != null && answer.getVariables() != null) {
@@ -173,13 +173,13 @@
   }
 
   /** {@inheritDoc} */
-  protected void addResults() throws TuplesException, IOException {
+  protected void addResults(Answer answer) throws TuplesException, IOException {
     if (answer != null) {
       comma().append("\"results\": { ");
       s.append("\"bindings\": [ ");
       answer.beforeFirst();
       prependComma = false;
-      while (answer.next()) addResult();
+      while (answer.next()) addResult(answer);
       s.append(" ] }");
     } else {
       comma().append("\"boolean\": ").append(Boolean.toString(booleanResult));
@@ -187,7 +187,7 @@
   }
 
   /** {@inheritDoc} */
-  protected void addResult() throws TuplesException, IOException {
+  protected void addResult(Answer answer) throws TuplesException, IOException {
     comma().append("{ ");
     prependComma = false;
     for (int c = 0; c < width; c++) addBinding(vars[c], answer.getObject(c));

Modified: trunk/src/jar/querylang/java/org/mulgara/protocol/StreamedSparqlXMLAnswer.java
===================================================================
--- trunk/src/jar/querylang/java/org/mulgara/protocol/StreamedSparqlXMLAnswer.java	2010-02-15 19:24:58 UTC (rev 1916)
+++ trunk/src/jar/querylang/java/org/mulgara/protocol/StreamedSparqlXMLAnswer.java	2010-02-15 19:27:38 UTC (rev 1917)
@@ -76,7 +76,7 @@
    * @param result The boolean result to encode.
    */
   public StreamedSparqlXMLAnswer(boolean result, OutputStream output) {
-    super(null, output);
+    super((Answer)null, output);
     booleanResult = result;
   }
 
@@ -86,7 +86,7 @@
    * @param metadata Additional metadata for the answer.
    */
   public StreamedSparqlXMLAnswer(boolean result, URI metadata, OutputStream output) {
-    super(null, output);
+    super((Answer)null, output);
     booleanResult = result;
     additionalMetadata = metadata;
   }
@@ -120,10 +120,10 @@
   }
 
   /** {@inheritDoc} */
-  protected void addHeader() throws IOException {
+  protected void addHeader(Answer a) throws IOException {
     s.append(i(1)).append("<head>");
-    if (answer != null && answer.getVariables() != null) {
-      for (Variable v: answer.getVariables()) addHeaderVariable(v);
+    if (a != null && a.getVariables() != null) {
+      for (Variable v: a.getVariables()) addHeaderVariable(v);
     }
     if (additionalMetadata != null) {
       s.append(i(2)).append("<link href=\"").append(additionalMetadata.toString()).append("\"/>");
@@ -138,11 +138,11 @@
   }
 
   /** {@inheritDoc} */
-  protected void addResults() throws TuplesException, IOException {
-    if (answer != null) {
+  protected void addResults(Answer a) throws TuplesException, IOException {
+    if (a != null) {
       s.append(i(1)).append("<results>");
-      answer.beforeFirst();
-      while (answer.next()) addResult();
+      a.beforeFirst();
+      while (a.next()) addResult(a);
       s.append(i(1)).append("</results>");
     } else {
       s.append(i(1)).append("<boolean>").append(Boolean.toString(booleanResult)).append("</boolean>");
@@ -150,9 +150,9 @@
   }
 
   /** {@inheritDoc} */
-  protected void addResult() throws TuplesException, IOException {
+  protected void addResult(Answer a) throws TuplesException, IOException {
     s.append(i(2)).append("<result>");
-    for (int c = 0; c < width; c++) addBinding(vars[c], answer.getObject(c));
+    for (int c = 0; c < width; c++) addBinding(vars[c], a.getObject(c));
     s.append(i(2)).append("</result>");
   }
 

Modified: trunk/src/jar/querylang/java/org/mulgara/protocol/StreamedTqlXMLAnswer.java
===================================================================
--- trunk/src/jar/querylang/java/org/mulgara/protocol/StreamedTqlXMLAnswer.java	2010-02-15 19:24:58 UTC (rev 1916)
+++ trunk/src/jar/querylang/java/org/mulgara/protocol/StreamedTqlXMLAnswer.java	2010-02-15 19:27:38 UTC (rev 1917)
@@ -18,6 +18,7 @@
 
 import java.io.IOException;
 import java.io.OutputStream;
+import java.util.List;
 
 import org.jrdf.graph.BlankNode;
 import org.jrdf.graph.Literal;
@@ -44,25 +45,33 @@
     setPrettyPrint(false);
   }
 
+  /**
+   * Creates an XML Answer for XML results. Pretty printing is off by default.
+   * @param answer The Answer to wrap.
+   */
+  public StreamedTqlXMLAnswer(List<Answer> answers, OutputStream output) {
+    super(answers, output);
+    setPrettyPrint(false);
+  }
+
   /** {@inheritDoc} */
   protected void addDocHeader() throws IOException {
     s.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
     s.append("<answer xmlns=\"http://mulgara.org/tql#\">");
-    s.append(i(1)).append("<query>");
   }
 
   /** {@inheritDoc} */
   protected void addDocFooter() throws IOException {
-    s.append(i(1)).append("</query>");
     s.append(i(0)).append("</answer>");
   }
 
   /** {@inheritDoc} */
-  protected void addHeader() throws IOException {
+  protected void addHeader(Answer answer) throws IOException {
     addHeader(answer, 0);
   }
 
   void addHeader(Answer a, int indent) throws IOException {
+    s.append(i(indent + 1)).append("<query>");
     s.append(i(indent + 2)).append("<variables>");
     if (a != null && a.getVariables() != null) for (Variable v: a.getVariables()) addHeaderVariable(v, indent);
     s.append(i(indent + 2)).append("</variables>");
@@ -79,23 +88,33 @@
   }
 
   /** {@inheritDoc} */
-  protected void addResults() throws TuplesException, IOException {
-    answer.beforeFirst();
-    while (answer.next()) addResult();
+  protected void addResults(Answer a) throws TuplesException, IOException {
+    a.beforeFirst();
+    while (a.next()) addResult(a);
+    s.append(i(1)).append("</query>");
   }
 
-  /** {@inheritDoc} */
+  /**
+   * Just like {@link #addResults(Answer)} only this is used for subanswers,
+   * so it may be indented, and does not have a trailing end of query section.
+   * @param a The current answer to get results from.
+   * @param indent The level of indentation to use.
+   */
   protected void addResults(Answer a, int indent) throws TuplesException, IOException {
     a.beforeFirst();
     while (a.next()) addResult(a, indent);
   }
 
   /** {@inheritDoc} */
-  protected void addResult() throws TuplesException, IOException {
-    addResult(answer, 0);
+  protected void addResult(Answer a) throws TuplesException, IOException {
+    addResult(a, 0);
   }
 
-  /** {@inheritDoc} */
+  /** 
+   * Prints a single row from an Answer, using the given indent.
+   * @param a The answer to get the row from.
+   * @param indent The indentation to use on the answer.
+   */
   protected void addResult(Answer a, int indent) throws TuplesException, IOException {
     int width = (a != null) ? a.getNumberOfVariables() : 0;
     Variable[] vars = (a != null) ? a.getVariables() : null;

Modified: trunk/src/jar/querylang/java/org/mulgara/protocol/http/ProtocolServlet.java
===================================================================
--- trunk/src/jar/querylang/java/org/mulgara/protocol/http/ProtocolServlet.java	2010-02-15 19:24:58 UTC (rev 1916)
+++ trunk/src/jar/querylang/java/org/mulgara/protocol/http/ProtocolServlet.java	2010-02-15 19:27:38 UTC (rev 1917)
@@ -337,6 +337,32 @@
 
 
   /**
+   * Execute a query on the database, and return the {@link Answer}.
+   * @param query The query to run.
+   * @param req The client request object.
+   * @return An Answer containing the results of the query.
+   * @throws ServletException Due to an error executing the query.
+   * @throws IOException If there was an error establishing a connection.
+   */
+  List<Answer> executeQuery(List<Query> queries, HttpServletRequest req) throws ServletException, IOException {
+    try {
+      final Connection connection = getConnection(req);
+      return C.map(queries,
+          new Fn1E<Query,Answer,Exception>() { public Answer fn(Query q) throws Exception { return q.execute(connection); } }
+      );
+    } catch (IllegalStateException e) {
+      throw new ServiceUnavailableException(e.getMessage());
+    } catch (QueryException e) {
+      throw new InternalErrorException(e.getMessage());
+    } catch (TuplesException e) {
+      throw new InternalErrorException(e.getMessage());
+    } catch (Exception e) {
+      throw new InternalErrorException("Unexpected error type: " + e.getMessage());
+    }
+  }
+
+
+  /**
    * Execute a command on the database, and return whatever the result is.
    * @param cmd The command to run.
    * @param req The client request object.




More information about the Mulgara-svn mailing list