blob: 894678059f7e32a4f8447a76a3102743b147fc1f [file] [log] [blame]
/*
* 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.riot;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Objects;
import org.apache.jena.atlas.io.IO;
import org.apache.jena.atlas.web.ContentType;
import org.apache.jena.graph.Graph;
import org.apache.jena.riot.system.RiotLib;
import org.apache.jena.sparql.core.DatasetGraph;
import org.apache.jena.sparql.util.Context;
/**
* An {@link RDFWriter} is a process that will output triples or quads in an RDF syntax.
* {@link RDFWriterBuilder} provides the means to setup the writer.
* <p>
* The process is
*
* <pre>
* DatasetGraph dsg = ...
* RDFWriter writer = RDFWriter.create().source(dsg).lang(Lang.TTL).build();
* OutputStream out =
* writer.output(out);
* </pre>
* or using abbreviated forms:
* <pre>
* RDFWriter.create().source(dsg).lang(Lang.TTL).output(out);
* </pre>
* @see WriterDatasetRIOT
* @see WriterGraphRIOT
*/
public class RDFWriter {
private static int BUF_SIZE = 128*1024;
private final DatasetGraph dataset;
private final Graph graph;
private final RDFFormat format;
private final String baseURI;
private final Context context;
/** Create an {@link RDFWriterBuilder}.
* <p>
* Often used in a pattern such as:
* <pre>
* RDFWriter.create()
* .lang(Lang.TTL)
* .source(graph)
* .output(System.out);
* </pre>
*/
public static RDFWriterBuilder create() { return new RDFWriterBuilder(); }
/*package*/ RDFWriter(DatasetGraph dataset, Graph graph, RDFFormat format, Lang lang, String baseURI, Context context) {
this.dataset = dataset;
this.graph = graph;
// format may still be null - output to a file later.
this.format = chooseFormat(format, lang);
this.baseURI = baseURI;
this.context = context;
}
private static RDFFormat chooseFormat(RDFFormat format, Lang lang) {
if ( format != null )
return format;
if ( lang == null )
//throw new RiotException("No syntax for output") ;
return null;
format = RDFWriterRegistry.defaultSerialization(lang);
return format;
}
/** Write and return as a string.
* <p>
* The {@code Lang} or {@code RDFFormat} must have been set.
*/
public String asString() {
if ( format == null )
throw new RiotException("Output as a string needs the Lang/Format specificied");
try ( StringWriter sw = new StringWriter() ) {
output(sw, format);
return sw.toString();
} catch (IOException ex) { IO.exception(ex); return null; }
}
/** Write the source to the {@code OutputStream}.
* <p>
* The {@code Lang} or {@code RDFFormat} must have been set.
* @param output
*/
public void output(OutputStream output) {
output(output, format);
}
/** Write the source to the Java {@code Writer}.
* <p>
* The {@code Lang} or {@code RDFFormat} must have been set.
* @param javaWriter
* @deprecated Using Java Writers risk corrupting the character set. Only UTF-8 is safe.
*/
@Deprecated
public void output(Writer javaWriter) {
output(javaWriter, format);
}
/** Write the source to the file.
* <p>
* If neither {@code Lang} nor {@code RDFFormat} are set, an attempt to
* guess an RDF Syntax is made from the file extension.
* <p>Output to "-" goes to stdout.
* @param filename
*/
public void output(String filename) {
Objects.requireNonNull(filename, "Null filename");
RDFFormat fmt = format;
if ( fmt == null ) {
ContentType ct = RDFLanguages.guessContentType(filename);
if ( ct == null )
throw new RiotException("Lang and RDFformat unset and can't determine syntax from '"+filename+"'");
Lang lang = RDFLanguages.contentTypeToLang(ct);
if ( lang == null )
throw new RiotException("No syntax registered for '"+ct.getContentTypeStr()+"'");
fmt = RDFWriterRegistry.defaultSerialization(lang);
}
if ( filename.equals("-") ) {
output(System.out, fmt);
return;
}
Path p = Paths.get(filename);
try ( OutputStream out1 = Files.newOutputStream(p);
OutputStream out = new BufferedOutputStream(out1, BUF_SIZE)){
output(out, fmt);
} catch (IOException ex) { IO.exception(ex); }
}
private void output(OutputStream output, RDFFormat format) {
if ( format == null )
throw new RiotException("No syntax (Lang or RDFFormat) for output") ;
if ( graph != null ) {
write$(output, graph, format);
return;
}
if ( dataset != null ) {
write$(output, dataset, format);
return;
}
throw new RiotException("No graph or dataset to write") ;
}
private void output(Writer javaWriter, RDFFormat format) {
if ( format == null )
throw new RiotException("No syntax (Lang or RDFFormat) for output") ;
if ( graph != null ) {
write$(javaWriter, graph, format);
return;
}
if ( dataset != null ) {
write$(javaWriter, dataset, format);
return;
}
throw new RiotException("No graph or dataset to write") ;
}
// Allowing an externally set PrefixMap was (probably) a mistake.
private static WriterGraphRIOT createGraphWriter$(RDFFormat serialization) {
WriterGraphRIOTFactory wf = RDFWriterRegistry.getWriterGraphFactory(serialization);
if ( wf == null )
throw new RiotException("No graph writer for " + serialization);
return wf.create(serialization);
}
private static WriterDatasetRIOT createDatasetWriter$(RDFFormat serialization) {
WriterDatasetRIOTFactory wf = RDFWriterRegistry.getWriterDatasetFactory(serialization);
if ( wf == null )
throw new RiotException("No dataset writer for " + serialization);
return wf.create(serialization);
}
private void write$(OutputStream out, Graph graph, RDFFormat serialization) {
WriterGraphRIOT w = createGraphWriter$(serialization);
w.write(out, graph, RiotLib.prefixMap(graph), baseURI, context);
}
private void write$(OutputStream out, DatasetGraph dataset, RDFFormat serialization) {
WriterDatasetRIOT w = createDatasetWriter$(serialization);
w.write(out, dataset, RiotLib.prefixMap(dataset), baseURI, context);
}
private void write$(Writer out, Graph graph, RDFFormat serialization) {
WriterGraphRIOT w = createGraphWriter$(serialization);
w.write(out, graph, RiotLib.prefixMap(graph), baseURI,context);
}
private void write$(Writer out, DatasetGraph dataset, RDFFormat serialization) {
WriterDatasetRIOT w = createDatasetWriter$(serialization);
w.write(out, dataset, RiotLib.prefixMap(dataset), baseURI, context);
}
}