001/**
002 * Copyright 2015 DuraSpace, Inc.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package org.fcrepo.transform.http.responses;
017
018import static com.hp.hpl.jena.query.ResultSetFormatter.output;
019import static com.hp.hpl.jena.query.ResultSetFormatter.toModel;
020import static com.hp.hpl.jena.sparql.resultset.ResultsFormat.FMT_RDF_NT;
021import static com.hp.hpl.jena.sparql.resultset.ResultsFormat.FMT_RDF_TTL;
022import static com.hp.hpl.jena.sparql.resultset.ResultsFormat.FMT_RDF_XML;
023import static com.hp.hpl.jena.sparql.resultset.ResultsFormat.FMT_RS_BIO;
024import static com.hp.hpl.jena.sparql.resultset.ResultsFormat.FMT_RS_CSV;
025import static com.hp.hpl.jena.sparql.resultset.ResultsFormat.FMT_RS_JSON;
026import static com.hp.hpl.jena.sparql.resultset.ResultsFormat.FMT_RS_TSV;
027import static com.hp.hpl.jena.sparql.resultset.ResultsFormat.FMT_RS_XML;
028import static com.hp.hpl.jena.sparql.resultset.ResultsFormat.FMT_UNKNOWN;
029import static org.apache.jena.riot.RDFLanguages.contentTypeToLang;
030import static org.apache.jena.riot.WebContent.contentTypeNTriples;
031import static org.apache.jena.riot.WebContent.contentTypeRDFXML;
032import static org.apache.jena.riot.WebContent.contentTypeResultsBIO;
033import static org.apache.jena.riot.WebContent.contentTypeResultsJSON;
034import static org.apache.jena.riot.WebContent.contentTypeResultsXML;
035import static org.apache.jena.riot.WebContent.contentTypeTextCSV;
036import static org.apache.jena.riot.WebContent.contentTypeTextTSV;
037import static org.apache.jena.riot.WebContent.contentTypeTurtle;
038import static org.apache.jena.riot.WebContent.contentTypeTurtleAlt1;
039import static org.apache.jena.riot.WebContent.contentTypeTurtleAlt2;
040
041import java.io.OutputStream;
042import java.lang.annotation.Annotation;
043import java.lang.reflect.Type;
044
045import javax.ws.rs.Produces;
046import javax.ws.rs.core.MediaType;
047import javax.ws.rs.core.MultivaluedMap;
048import javax.ws.rs.ext.MessageBodyWriter;
049import javax.ws.rs.ext.Provider;
050
051import org.apache.jena.riot.Lang;
052
053import com.hp.hpl.jena.query.ResultSet;
054import com.hp.hpl.jena.rdf.model.Model;
055import com.hp.hpl.jena.sparql.resultset.ResultsFormat;
056
057/**
058 * Stream the results of a SPARQL Query
059 *
060 * @author cbeer
061 */
062@Provider
063@Produces({contentTypeTextTSV, contentTypeTextCSV, contentTypeResultsJSON,
064        contentTypeResultsXML, contentTypeResultsBIO, contentTypeTurtle,
065        contentTypeNTriples, contentTypeRDFXML})
066public class ResultSetStreamingOutput implements MessageBodyWriter<ResultSet> {
067
068
069
070    @Override
071    public boolean isWriteable(final Class<?> type,
072                               final Type genericType,
073                               final Annotation[] annotations,
074                               final MediaType mediaType) {
075        final ResultsFormat resultsFormat = getResultsFormat(mediaType);
076
077        if (resultsFormat == FMT_UNKNOWN) {
078            final Lang format = contentTypeToLang(mediaType.toString());
079
080            return format != null;
081        }
082        return true;
083    }
084
085    @Override
086    public long getSize(final ResultSet resultSet,
087                        final Class<?> type,
088                        final Type genericType,
089                        final Annotation[] annotations,
090                        final MediaType mediaType) {
091        return -1;
092    }
093
094    @Override
095    public void writeTo(final ResultSet resultSet,
096                        final Class<?> type,
097                        final Type genericType,
098                        final Annotation[] annotations,
099                        final MediaType mediaType,
100                        final MultivaluedMap<String, Object> httpHeaders,
101                        final OutputStream entityStream) {
102        final ResultsFormat resultsFormat = getResultsFormat(mediaType);
103
104        if (resultsFormat == FMT_UNKNOWN) {
105            final String format = contentTypeToLang(mediaType.toString()).getName().toUpperCase();
106            final Model model = toModel(resultSet);
107            model.write(entityStream, format);
108        } else {
109            output(entityStream, resultSet, resultsFormat);
110        }
111    }
112
113    /**
114     * Map the HTTP MediaType to a SPARQL ResultsFormat
115     * @param mediaType the media type
116     * @return SPARQL {@link ResultsFormat} for the given {@link MediaType}
117     */
118    public static ResultsFormat getResultsFormat(final MediaType mediaType) {
119        switch (mediaType.toString()) {
120            case contentTypeTextTSV:
121                return FMT_RS_TSV;
122
123            case contentTypeTextCSV:
124                return FMT_RS_CSV;
125
126            case contentTypeResultsJSON:
127                return FMT_RS_JSON;
128
129            case contentTypeResultsXML:
130                return FMT_RS_XML;
131
132            case contentTypeResultsBIO:
133                return FMT_RS_BIO;
134
135            case contentTypeTurtle:
136            case contentTypeTurtleAlt1:
137            case contentTypeTurtleAlt2:
138                return FMT_RDF_TTL;
139
140            case contentTypeNTriples:
141                return FMT_RDF_NT;
142
143            case contentTypeRDFXML:
144                return FMT_RDF_XML;
145            default:
146                return FMT_UNKNOWN;
147        }
148    }
149}