blob: 20b9294b1952e21fec64789be3b1956cc21e896e [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.system;
import java.io.OutputStream;
import java.io.Writer;
import org.apache.jena.atlas.io.AWriter;
import org.apache.jena.atlas.io.IO;
import org.apache.jena.atlas.lib.CharSpace;
import org.apache.jena.atlas.lib.Sink;
import org.apache.jena.graph.Graph;
import org.apache.jena.graph.Node;
import org.apache.jena.graph.Triple;
import org.apache.jena.riot.lang.StreamRDFCounting;
import org.apache.jena.riot.writer.WriterStreamRDFPlain;
import org.apache.jena.shared.JenaException;
import org.apache.jena.sparql.core.DatasetGraph;
import org.apache.jena.sparql.core.Quad;
/** Various Common StreamRDF setups */
public class StreamRDFLib
{
/** Send everything to nowhere ... efficiently */
public static StreamRDF sinkNull() { return new StreamRDFBase(); }
/**
* Create a {@link StreamRDF} that prints to an {@link OutputStream}.
* This is debug output.
*/
public static StreamRDF print(OutputStream out) { return new PrintingStreamRDF(out); }
/**
* Create a {@link StreamRDF} that prints to an {@link AWriter}.
* This is debug output.
*/
public static StreamRDF print(AWriter out) { return new PrintingStreamRDF(out); }
/**
* Create a {@link StreamRDF} that outputs to an {@link OutputStream}. It is important
* to call {@link StreamRDF#start} and {@link StreamRDF#finish} because the output is
* buffered.
*/
public static StreamRDF writer(OutputStream out) { return new WriterStreamRDFPlain(IO.wrapUTF8(out)); }
/** Create a {@link StreamRDF} that outputs to an {@link AWriter}. */
public static StreamRDF writer(AWriter out) { return new WriterStreamRDFPlain(out); }
/**
* Create a {@link StreamRDF} that outputs to an {@link Writer}. It is important to
* call {@link StreamRDF#start} and {@link StreamRDF#finish} because the output is
* buffered.
*/
public static StreamRDF writer(Writer out) { return new WriterStreamRDFPlain(IO.wrap(out)); }
/**
* Create a {@link StreamRDF} that outputs to an {@link OutputStream} with a specific
* {@link CharSpace} (ASCII or UTF-8).
* <p>
* It is important to call {@link StreamRDF#start}
* and {@link StreamRDF#finish} because the output is buffered.
*/
public static StreamRDF writer(OutputStream out, CharSpace charSpace) {
switch (charSpace) {
case ASCII :
return new WriterStreamRDFPlain(IO.wrapASCII(out), charSpace);
case UTF8 :
default :
return writer(out);
}
}
/**
* Create a {@link StreamRDF} that outputs to an {@link OutputStream} with a specific
* {@link CharSpace} (ASCII or UTF-8).
* <p>
* It is important to call {@link StreamRDF#start}
* and {@link StreamRDF#finish} because the output is buffered.
*/
public static StreamRDF writer(AWriter out, CharSpace charSpace) {
return new WriterStreamRDFPlain(out, charSpace);
}
/**
* Create a {@link StreamRDF} that outputs to an {@link Writer} with a specific
* {@link CharSpace} (ASCII or UTF-8) writing out-of-range codepoints (if ASCII)
* as "\ uXXXX".
* <p>
* It is important to call {@link StreamRDF#start}
* and {@link StreamRDF#finish} because the output is buffered.
*/
public static StreamRDF writer(Writer out, CharSpace charSpace) {
return new WriterStreamRDFPlain(IO.wrap(out), charSpace);
}
public static StreamRDF graph(Graph graph) { return new ParserOutputGraph(graph); }
public static StreamRDF dataset(DatasetGraph dataset) { return new ParserOutputDataset(dataset); }
/**
* Output to a sink; prefix and base handled only within the parser.
* Unfortunately, Java needs different names for the triples and
* quads versions because of type erasure.
*/
public static StreamRDF sinkTriples(Sink<Triple> sink) { return new ParserOutputSinkTriples(sink); }
/**
* Output to a sink; prefix and base handled only within the parser.
* Unfortunately, Java needs different names for the triples and
* quads versions because of type erasure.
*/
public static StreamRDF sinkQuads(Sink<Quad> sink) { return new ParserOutputSinkQuads(sink); }
/** Convert any triples seen to a quads, adding a graph node of {@link Quad#tripleInQuad} */
public static StreamRDF extendTriplesToQuads(StreamRDF base)
{ return extendTriplesToQuads(Quad.tripleInQuad, base); }
/** Convert any triples seen to a quads, adding the specified graph node */
public static StreamRDF extendTriplesToQuads(Node graphNode, StreamRDF base)
{ return new ParserOutputSinkTriplesToQuads(graphNode, base); }
public static StreamRDFCounting count()
{ return new StreamRDFCountingBase(sinkNull()); }
public static StreamRDFCounting count(StreamRDF other)
{ return new StreamRDFCountingBase(other); }
private static class ParserOutputSinkTriplesToQuads extends StreamRDFWrapper
{
private final Node gn;
ParserOutputSinkTriplesToQuads(Node gn, StreamRDF base)
{ super(base); this.gn = gn; }
@Override public void triple(Triple triple)
{ other.quad(new Quad(gn, triple)); }
}
private static class ParserOutputSinkTriples extends StreamRDFBase
{
private final Sink<Triple> sink;
public ParserOutputSinkTriples(Sink<Triple> sink)
{ this.sink = sink; }
@Override
public void triple(Triple triple)
{ sink.send(triple); }
@Override
public void finish()
{ sink.flush(); }
}
private static class ParserOutputSinkQuads extends StreamRDFBase
{
private final Sink<Quad> sink;
public ParserOutputSinkQuads(Sink<Quad> sink)
{ this.sink = sink; }
@Override
public void quad(Quad quad)
{ sink.send(quad); }
@Override
public void finish()
{ sink.flush(); }
}
private static class ParserOutputGraph extends StreamRDFBase {
protected final Graph graph;
protected boolean warningIssued = false;
public ParserOutputGraph(Graph graph) {
this.graph = graph;
}
@Override
public void triple(Triple triple) {
graph.add(triple);
}
@Override
public void quad(Quad quad) {
if ( quad.isTriple() || quad.isDefaultGraph() )
graph.add(quad.asTriple());
else {
if ( !warningIssued ) {
// SysRIOT.getLogger().warn("Only triples or default graph data expected : named graph data ignored");
// Not ideal - assumes the global default.
ErrorHandlerFactory.getDefaultErrorHandler()
.warning("Only triples or default graph data expected : named graph data ignored", -1, -1);
}
warningIssued = true;
}
// throw new IllegalStateException("Quad passed to graph parsing");
}
@Override
public void base(String base) {}
@Override
public void prefix(String prefix, String uri) {
try { // Some graphs apply XML rules to prefixes.
graph.getPrefixMapping().setNsPrefix(prefix, uri);
} catch (JenaException ex) {}
}
}
private static class ParserOutputDataset extends StreamRDFBase {
protected final DatasetGraph dsg;
protected final PrefixMap prefixMap;
public ParserOutputDataset(DatasetGraph dsg) {
this.dsg = dsg;
this.prefixMap = dsg.prefixes();
}
@Override
public void triple(Triple triple) {
dsg.add(Quad.defaultGraphNodeGenerated, triple.getSubject(), triple.getPredicate(), triple.getObject());
}
@Override
public void quad(Quad quad) {
if ( quad.isTriple() )
dsg.add(Quad.defaultGraphNodeGenerated, quad.getSubject(), quad.getPredicate(), quad.getObject());
else
dsg.add(quad);
}
@Override
public void base(String base) {}
@Override
public void prefix(String prefix, String uri) {
try {
// Some datasets may be tied to PrefixMappings and may apply XML
// rules to prefixes.
prefixMap.add(prefix, uri);
} catch (JenaException ex) {}
}
}
}