You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by an...@apache.org on 2015/08/20 13:08:38 UTC
[07/16] jena git commit: Reworking CONSTRUCT for quads.
Reworking CONSTRUCT for quads.
GSOC JENA 491 final.
Project: http://git-wip-us.apache.org/repos/asf/jena/repo
Commit: http://git-wip-us.apache.org/repos/asf/jena/commit/077a4136
Tree: http://git-wip-us.apache.org/repos/asf/jena/tree/077a4136
Diff: http://git-wip-us.apache.org/repos/asf/jena/diff/077a4136
Branch: refs/heads/JENA-491-construct-quads
Commit: 077a413662c19f8ac063e236d7bdd5f652fef3cb
Parents: 3ac6a5a 602e3c0
Author: Andy Seaborne <an...@apache.org>
Authored: Thu Aug 20 09:39:26 2015 +0100
Committer: Andy Seaborne <an...@apache.org>
Committed: Thu Aug 20 09:39:43 2015 +0100
----------------------------------------------------------------------
.../org/apache/jena/atlas/web/AcceptList.java | 145 ++--
.../sparql/engine/http/QueryEngineHTTP.java | 43 +-
.../main/java/org/apache/jena/fuseki/DEF.java | 17 +-
.../jena/fuseki/servlets/ResponseDataset.java | 20 +-
.../jena/fuseki/servlets/ResponseModel.java | 5 +
.../jena/fuseki/servlets/SPARQL_Query.java | 838 +++++++++----------
.../java/org/apache/jena/fuseki/TestQuery.java | 260 ++++--
7 files changed, 699 insertions(+), 629 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jena/blob/077a4136/jena-arq/src/main/java/org/apache/jena/atlas/web/AcceptList.java
----------------------------------------------------------------------
diff --cc jena-arq/src/main/java/org/apache/jena/atlas/web/AcceptList.java
index 8801016,e3eb290..1d251c8
--- a/jena-arq/src/main/java/org/apache/jena/atlas/web/AcceptList.java
+++ b/jena-arq/src/main/java/org/apache/jena/atlas/web/AcceptList.java
@@@ -54,27 -54,27 +54,24 @@@ public class AcceptLis
* @param acceptItems
*/
-- public static AcceptList create(MediaType...acceptItems)
-- {
-- AcceptList accepList = new AcceptList() ;
++ public static AcceptList create(MediaType... acceptItems) {
++ AcceptList accepList = new AcceptList();
for ( MediaType mtype : acceptItems )
-- accepList.ranges.add(new MediaRange(mtype)) ;
-- return accepList ;
-- }
++ accepList.ranges.add(new MediaRange(mtype));
++ return accepList;
++ }
/**
* Create a list of accept items from strings.
* @param acceptStrings
*/
-- public static AcceptList create(String... acceptStrings)
-- {
-- AcceptList accepList = new AcceptList() ;
-- for ( String acceptString : acceptStrings )
-- {
-- accepList.ranges.add( new MediaRange( acceptString ) );
++ public static AcceptList create(String... acceptStrings) {
++ AcceptList accepList = new AcceptList();
++ for ( String acceptString : acceptStrings ) {
++ accepList.ranges.add(new MediaRange(acceptString));
}
-- return accepList ;
++ return accepList;
}
/**
@@@ -82,26 -82,26 +79,23 @@@
* @param headerString
*/
-- public AcceptList(String headerString)
-- {
++ public AcceptList(String headerString) {
try {
-- ranges = stringToAcceptList(headerString) ;
-- } catch (Exception ex)
-- {
-- ex.printStackTrace(System.err) ;
-- Log.warn(this, "Unrecognized accept string (ignored): "+headerString) ;
-- ranges = new ArrayList<>() ;
++ ranges = stringToAcceptList(headerString);
++ }
++ catch (Exception ex) {
++ ex.printStackTrace(System.err);
++ Log.warn(this, "Unrecognized accept string (ignored): " + headerString);
++ ranges = new ArrayList<>();
}
}
--
-- private /*public*/ boolean accepts(MediaRange aItem)
-- {
-- return match(aItem) != null ;
++
++ private /* public */ boolean accepts(MediaRange aItem) {
++ return match(aItem) != null;
}
- private List<MediaRange> entries()
- public List<MediaRange> entries()
-- {
-- return Collections.unmodifiableList(ranges) ;
++ public List<MediaRange> entries() {
++ return Collections.unmodifiableList(ranges);
}
private final static MediaRangeCompare comparator = new MediaRangeCompare() ;
@@@ -119,11 -119,11 +113,9 @@@
double weight = -1 ;
int exact = -1 ;
-- for ( MediaRange acceptItem : ranges )
-- {
-- if ( acceptItem.accepts(offer) )
-- {
-- boolean newChoice = false;
++ for ( MediaRange acceptItem : ranges ) {
++ if ( acceptItem.accepts(offer) ) {
++ boolean newChoice = false;
if ( choice == null )
// First possibility.
newChoice = true ;
@@@ -134,12 -134,12 +126,11 @@@
// New possibility has same weight but better exactness.
newChoice = true ;
-- if ( newChoice )
-- {
-- choice = acceptItem ;
-- weight = acceptItem.get_q() ;
-- exact = acceptItem.subweight() ;
-- continue ;
++ if ( newChoice ) {
++ choice = acceptItem;
++ weight = acceptItem.get_q();
++ exact = acceptItem.subweight();
++ continue;
}
//if ( weight == acceptItem.get_q() && !exact &&
}
@@@ -157,19 -157,19 +148,17 @@@
* @return MediaType
*/
-- static public MediaType match(AcceptList proposalList, AcceptList offerList)
-- {
-- MediaRange cause = null ;
++ static public MediaType match(AcceptList proposalList, AcceptList offerList) {
++ MediaRange cause = null;
MediaRange choice = null ; // From the proposalList
double weight = -1 ;
int exactness = -1 ;
-- for ( MediaRange offer : offerList.entries() )
-- {
-- MediaRange m = proposalList.match(offer) ;
++ for ( MediaRange offer : offerList.entries() ) {
++ MediaRange m = proposalList.match(offer);
if ( m == null )
-- continue ;
-- boolean newChoice = false ;
++ continue;
++ boolean newChoice = false;
if ( choice == null )
newChoice = true ;
@@@ -185,51 -185,51 +174,43 @@@
}
}
--
if ( choice == null )
return null ;
return new MediaType(choice);
}
-- public MediaRange first()
-- {
-- MediaRange choice = null ;
-- for ( MediaRange acceptItem : ranges )
-- {
++ public MediaRange first() {
++ MediaRange choice = null;
++ for ( MediaRange acceptItem : ranges ) {
if ( choice != null && choice.get_q() >= acceptItem.get_q() )
-- continue ;
-- choice = acceptItem ;
++ continue;
++ choice = acceptItem;
}
-- return choice ;
++ return choice;
}
--
++
@Override
public String toString() { return ranges.toString() ; }
-- private static List<MediaRange> stringToAcceptList(String s)
-- {
-- List<MediaRange> ranges = new ArrayList<>() ;
++ private static List<MediaRange> stringToAcceptList(String s) {
++ List<MediaRange> ranges = new ArrayList<>();
if ( s == null )
-- return ranges ;
++ return ranges;
-- String[] x = s.split(",") ;
-- for ( String aX : x )
-- {
-- if ( aX.equals( "" ) )
-- {
++ String[] x = s.split(",");
++ for ( String aX : x ) {
++ if ( aX.equals("") ) {
continue;
}
-- MediaRange mType = new MediaRange( aX );
-- ranges.add( mType );
++ MediaRange mType = new MediaRange(aX);
++ ranges.add(mType);
}
-- return ranges ;
++ return ranges;
}
-- private static class MediaRangeCompare implements Comparator<MediaRange>
-- {
++ private static class MediaRangeCompare implements Comparator<MediaRange> {
@Override
-- public int compare(MediaRange mType1, MediaRange mType2)
-- {
++ public int compare(MediaRange mType1, MediaRange mType2) {
int r = Double.compare(mType1.get_q(), mType2.get_q()) ;
if ( r == 0 )
@@@ -238,8 -238,8 +219,7 @@@
if ( r == 0 )
r = subCompare(mType1.getSubType(), mType2.getSubType()) ;
--// if ( r == 0 )
--// {
++// if ( r == 0 ) {
// // This reverses the input order so that the rightmost elements is the
// // greatest and hence is the first mentioned in the accept range.
//
@@@ -254,19 -254,19 +234,18 @@@
return r ;
}
-- public int subCompare(String a, String b)
-- {
++ public int subCompare(String a, String b) {
if ( a == null )
-- return 1 ;
++ return 1;
if ( b == null )
-- return -1 ;
++ return -1;
if ( a.equals("*") && b.equals("*") )
-- return 0 ;
++ return 0;
if ( a.equals("*") )
-- return -1 ;
++ return -1;
if ( b.equals("*") )
-- return 1 ;
-- return 0 ;
++ return 1;
++ return 0;
}
}
}
http://git-wip-us.apache.org/repos/asf/jena/blob/077a4136/jena-arq/src/main/java/org/apache/jena/sparql/engine/http/QueryEngineHTTP.java
----------------------------------------------------------------------
diff --cc jena-arq/src/main/java/org/apache/jena/sparql/engine/http/QueryEngineHTTP.java
index cab831f,abe4d1f..2fa9602
--- a/jena-arq/src/main/java/org/apache/jena/sparql/engine/http/QueryEngineHTTP.java
+++ b/jena-arq/src/main/java/org/apache/jena/sparql/engine/http/QueryEngineHTTP.java
@@@ -85,6 -87,9 +87,10 @@@ public class QueryEngineHTTP implement
private String selectContentType = defaultSelectHeader();
private String askContentType = defaultAskHeader();
private String modelContentType = defaultConstructHeader();
+ private String datasetContentType = WebContent.defaultDatasetAcceptHeader;
+
- private String httpResponseContentType;
++ // Received content type
++ private String httpResponseContentType = null ;
/**
* Supported content types for SELECT queries
*/
@@@ -332,7 -337,11 +338,12 @@@
this.authenticator = authenticator;
}
- @Override
++ /** The Content-Type response header received (null before the remote operation is attempted). */
+ public String getHttpResponseContentType() {
+ return httpResponseContentType;
+ }
+
+ @Override
public ResultSet execSelect() {
checkNotClosed() ;
ResultSet rs = execResultSetInner() ;
@@@ -355,9 -364,10 +366,10 @@@
retainedConnection = in; // This will be closed on close()
retainedClient = httpQuery.shouldShutdownClient() ? httpQuery.getClient() : null;
-- // Don't assume the endpoint actually gives back the content type we
-- // asked for
++ // Don't assume the endpoint actually gives back the
++ // content type we asked for
String actualContentType = httpQuery.getContentType();
+ httpResponseContentType = actualContentType;
// If the server fails to return a Content-Type then we will assume
// the server returned the type we asked for
@@@ -399,7 -409,20 +411,14 @@@
@Override
public Dataset execConstructDataset(){
- return null;
-
- DatasetGraph graph = DatasetGraphFactory.createMem();
-
+ checkNotClosed() ;
- try
- {
- execConstructQuads().forEachRemaining(graph::add);
- }
- finally
- {
++ DatasetGraph dataset = DatasetGraphFactory.createMem();
++ try {
++ execConstructQuads().forEachRemaining(dataset::add);
++ } finally {
+ this.close();
+ }
- return DatasetFactory.create(graph);
-
++ return DatasetFactory.create(dataset);
}
@Override
http://git-wip-us.apache.org/repos/asf/jena/blob/077a4136/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ResponseDataset.java
----------------------------------------------------------------------
diff --cc jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ResponseDataset.java
index e12493d,5242f4b..1464b99
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ResponseDataset.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ResponseDataset.java
@@@ -18,7 -18,15 +18,8 @@@
package org.apache.jena.fuseki.servlets;
--import static org.apache.jena.riot.WebContent.charsetUTF8;
-import static org.apache.jena.riot.WebContent.contentTypeNQuads;
-import static org.apache.jena.riot.WebContent.contentTypeTriG;
-import static org.apache.jena.riot.WebContent.contentTypeJSONLD;
-import static org.apache.jena.riot.WebContent.contentTypeNTriples;
-import static org.apache.jena.riot.WebContent.contentTypeRDFJSON;
-import static org.apache.jena.riot.WebContent.contentTypeRDFXML;
-import static org.apache.jena.riot.WebContent.contentTypeTurtle;
++import static org.apache.jena.riot.WebContent.* ;
+
import java.util.HashMap;
import java.util.Map;
@@@ -41,17 -48,31 +42,28 @@@ import org.apache.jena.web.HttpSC
public class ResponseDataset
{
// Short names for "output="
- private static final String contentOutputTriG = "trig" ;
- private static final String contentOutputNQuads = "n-quads" ;
+ private static final String contentOutputJSONLD = "json-ld" ;
+ private static final String contentOutputJSONRDF = "json-rdf" ;
+ private static final String contentOutputJSON = "json" ;
+ private static final String contentOutputXML = "xml" ;
+ private static final String contentOutputText = "text" ;
+ private static final String contentOutputTTL = "ttl" ;
+ private static final String contentOutputNT = "nt" ;
-
+ private static final String contentOutputTriG = "trig" ;
+ private static final String contentOutputNQuads = "n-quads" ;
-
public static Map<String,String> shortNamesModel = new HashMap<String, String>() ;
static {
--
// Some short names. keys are lowercase.
--
- ResponseOps.put(shortNamesModel, contentOutputNQuads, contentTypeNQuads) ;
- ResponseOps.put(shortNamesModel, contentOutputTriG, contentTypeTriG) ;
+ ResponseOps.put(shortNamesModel, contentOutputJSONLD, contentTypeJSONLD) ;
+ ResponseOps.put(shortNamesModel, contentOutputJSONRDF, contentTypeRDFJSON) ;
+ ResponseOps.put(shortNamesModel, contentOutputJSON, contentTypeJSONLD) ;
+ ResponseOps.put(shortNamesModel, contentOutputXML, contentTypeRDFXML) ;
+ ResponseOps.put(shortNamesModel, contentOutputText, contentTypeTurtle) ;
+ ResponseOps.put(shortNamesModel, contentOutputTTL, contentTypeTurtle) ;
+ ResponseOps.put(shortNamesModel, contentOutputNT, contentTypeNTriples) ;
+ ResponseOps.put(shortNamesModel, contentOutputNQuads, WebContent.contentTypeNQuads) ;
+ ResponseOps.put(shortNamesModel, contentOutputTriG, WebContent.contentTypeTriG) ;
}
public static void doResponseDataset(HttpAction action, Dataset dataset)
http://git-wip-us.apache.org/repos/asf/jena/blob/077a4136/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ResponseModel.java
----------------------------------------------------------------------
diff --cc jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ResponseModel.java
index 68cf016,0000000..e46fbe6
mode 100644,000000..100644
--- a/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ResponseModel.java
+++ b/jena-fuseki2/jena-fuseki-core/src/main/java/org/apache/jena/fuseki/servlets/ResponseModel.java
@@@ -1,135 -1,0 +1,140 @@@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.jena.fuseki.servlets;
+
+import java.util.HashMap ;
+import java.util.Map ;
+
+import javax.servlet.ServletOutputStream ;
+import javax.servlet.http.HttpServletRequest ;
+import javax.servlet.http.HttpServletResponse ;
+
+import org.apache.jena.atlas.web.MediaType ;
+import org.apache.jena.fuseki.DEF ;
+import org.apache.jena.fuseki.Fuseki ;
+import org.apache.jena.fuseki.conneg.ConNeg ;
+import org.apache.jena.fuseki.conneg.WebLib ;
+import org.apache.jena.rdf.model.Model ;
+import org.apache.jena.riot.Lang ;
+import org.apache.jena.riot.RDFDataMgr ;
+import org.apache.jena.riot.RDFLanguages ;
+import static org.apache.jena.riot.WebContent.* ;
+import org.apache.jena.web.HttpSC ;
+
++// REPLACED by RssponseDataset
++// Kept here in case we need to revert it (Aug 2015)
++// Delete after release of Fusek 2.3.1 or earlier if specific confirmation
++// the new code is OK.
++
+public class ResponseModel
+{
+ // Short names for "output="
+ private static final String contentOutputJSONLD = "json-ld" ;
+ private static final String contentOutputJSONRDF = "json-rdf" ;
+ private static final String contentOutputJSON = "json" ;
+ private static final String contentOutputXML = "xml" ;
+ private static final String contentOutputText = "text" ;
+ private static final String contentOutputTTL = "ttl" ;
+ private static final String contentOutputNT = "nt" ;
+
+ public static Map<String,String> shortNamesModel = new HashMap<String, String>() ;
+ static {
+
+ // Some short names. keys are lowercase.
+ ResponseOps.put(shortNamesModel, contentOutputJSONLD, contentTypeJSONLD) ;
+ ResponseOps.put(shortNamesModel, contentOutputJSONRDF, contentTypeRDFJSON) ;
+ ResponseOps.put(shortNamesModel, contentOutputJSON, contentTypeJSONLD) ;
+ ResponseOps.put(shortNamesModel, contentOutputXML, contentTypeRDFXML) ;
+ ResponseOps.put(shortNamesModel, contentOutputText, contentTypeTurtle) ;
+ ResponseOps.put(shortNamesModel, contentOutputTTL, contentTypeTurtle) ;
+ ResponseOps.put(shortNamesModel, contentOutputNT, contentTypeNTriples) ;
+ }
+
+ public static void doResponseModel(HttpAction action, Model model)
+ {
+ HttpServletRequest request = action.request ;
+ HttpServletResponse response = action.response ;
+
+ String mimeType = null ; // Header request type
+
+ // TODO Use MediaType throughout.
+ MediaType i = ConNeg.chooseContentType(request, DEF.rdfOffer, DEF.acceptRDFXML) ;
+ if ( i != null )
+ mimeType = i.getContentType() ;
+
+ String outputField = ResponseOps.paramOutput(request, shortNamesModel) ;
+ if ( outputField != null )
+ mimeType = outputField ;
+
+ String writerMimeType = mimeType ;
+
+ if ( mimeType == null )
+ {
+ Fuseki.actionLog.warn("Can't find MIME type for response") ;
+ String x = WebLib.getAccept(request) ;
+ String msg ;
+ if ( x == null )
+ msg = "No Accept: header" ;
+ else
+ msg = "Accept: "+x+" : Not understood" ;
+ ServletOps.error(HttpSC.NOT_ACCEPTABLE_406, msg) ;
+ }
+
+ String contentType = mimeType ;
+ String charset = charsetUTF8 ;
+
+ String forceAccept = ResponseOps.paramForceAccept(request) ;
+ if ( forceAccept != null )
+ {
+ contentType = forceAccept ;
+ charset = charsetUTF8 ;
+ }
+
+ Lang lang = RDFLanguages.contentTypeToLang(contentType) ;
+ if ( lang == null )
+ ServletOps.errorBadRequest("Can't determine output content type: "+contentType) ;
+
+// if ( rdfw instanceof RDFXMLWriterI )
+// rdfw.setProperty("showXmlDeclaration", "true") ;
+
+ // // Write locally to check it's possible.
+ // // Time/space tradeoff.
+ // try {
+ // OutputStream out = new NullOutputStream() ;
+ // RDFDataMgr.write(out, model, lang) ;
+ // IO.flush(out) ;
+ // } catch (JenaException ex)
+ // {
+ // SPARQL_ServletBase.errorOccurred(ex) ;
+ // }
+
+ try {
+ ResponseResultSet.setHttpResponse(action, contentType, charset) ;
+ response.setStatus(HttpSC.OK_200) ;
+ ServletOutputStream out = response.getOutputStream() ;
+ RDFDataMgr.write(out, model, lang) ;
+ out.flush() ;
+ }
+ catch (Exception ex) {
+ action.log.info("Exception while writing the response model: "+ex.getMessage(), ex) ;
+ ServletOps.errorOccurred("Exception while writing the response model: "+ex.getMessage(), ex) ;
+ }
+ }
+}
+
http://git-wip-us.apache.org/repos/asf/jena/blob/077a4136/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/TestQuery.java
----------------------------------------------------------------------
diff --cc jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/TestQuery.java
index 911d105,5a57da3..1c496f0
--- a/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/TestQuery.java
+++ b/jena-fuseki2/jena-fuseki-core/src/test/java/org/apache/jena/fuseki/TestQuery.java
@@@ -126,18 -187,47 +187,46 @@@ public class TestQuery extends BaseTes
}
}
-
+ @Test
+ public void query_construct_02()
+ {
+ String query = " CONSTRUCT {?s ?p ?o} WHERE {?s ?p ?o}" ;
+ try ( QueryExecution qExec = QueryExecutionFactory.sparqlService(serviceQuery, query) ) {
+ Model result = qExec.execConstruct();
+ assertEquals(1, result.size());
+ }
+ }
- @Test public void request_id_header_01() throws IOException
+ @Test
+ public void query_construct_conneg()
{
- String qs = Convert.encWWWForm("ASK{}") ;
- URL u = new URL(serviceQuery+"?query="+qs);
- HttpURLConnection conn = (HttpURLConnection) u.openConnection();
- Assert.assertTrue(conn.getHeaderField("Fuseki-Request-ID") != null);
+ String query = " CONSTRUCT {?s ?p ?o} WHERE {?s ?p ?o}" ;
+ for (MediaType type: DEF.rdfOffer.entries()){
+ String contentType = type.toHeaderString();
+ try ( QueryEngineHTTP qExec = (QueryEngineHTTP) QueryExecutionFactory.sparqlService(serviceQuery, query) ) {
+ qExec.setModelContentType(initConstructContentTypes( contentType ) );
+ qExec.execConstruct();
+ assertEquals( contentType , qExec.getHttpResponseContentType());
+ }
+ }
}
-
- private void execQuery(String queryString, int exceptedRowCount)
+
+ @Test
+ public void query_construct_quad_conneg()
{
+ String queryString = " CONSTRUCT { GRAPH ?g {?s ?p ?o} } WHERE { GRAPH ?g {?s ?p ?o}}" ;
+ Query query = QueryFactory.create(queryString, Syntax.syntaxARQ);
+ for (MediaType type: DEF.quadsOffer.entries()){
+ String contentType = type.toHeaderString();
+ try ( QueryEngineHTTP qExec = (QueryEngineHTTP) QueryExecutionFactory.sparqlService(serviceQuery, query) ) {
+ qExec.setDatasetContentType(initConstructContentTypes( contentType ) );
+ qExec.execConstructQuads();
+ assertEquals( contentType , qExec.getHttpResponseContentType());
+ }
+ }
+ }
-
+
+ private void execQuery(String queryString, int exceptedRowCount) {
QueryExecution qExec = QueryExecutionFactory.sparqlService(serviceQuery, queryString) ;
ResultSet rs = qExec.execSelect() ;
int x = ResultSetFormatter.consume(rs) ;