/* * 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.sparql.engine.binding; import java.io.IOException ; import java.io.OutputStream ; import java.io.Writer ; import java.util.List ; import java.util.Map ; import org.apache.jena.atlas.io.IO ; import org.apache.jena.atlas.io.AWriter ; import org.apache.jena.atlas.iterator.Iter ; import org.apache.jena.atlas.lib.Sink ; import org.apache.jena.graph.Node ; import org.apache.jena.iri.IRI ; import org.apache.jena.riot.RiotException ; import org.apache.jena.riot.out.NodeFormatter ; import org.apache.jena.riot.out.NodeFormatterTTL ; import org.apache.jena.riot.system.PrefixMap ; import org.apache.jena.sparql.core.Var ; /** Parser for the RDF Tuples language */ public class BindingOutputStream implements Sink<Binding> { private final AWriter bw ; private Binding lastBinding = null ; private List<Var> vars = null ; private PrefixMap pmap ; private NodeFormatter nodeFormatter ; private boolean needOutputPMap = true ; private boolean needOutputVars = true ; public BindingOutputStream(OutputStream out) { this(out, null, null) ; } public BindingOutputStream(OutputStream out, PrefixMap prefixMapping) { this(out, null, prefixMapping) ; } public BindingOutputStream(OutputStream out, List<Var> vars) { this(out, vars, null) ; } public BindingOutputStream(OutputStream out, List<Var> vars, PrefixMap prefixMapping) { //this( BufferingWriter.create(out) , vars, prefixMapping) ; this( IO.asBufferedUTF8(out), vars, prefixMapping) ; } private BindingOutputStream(Writer out, List<Var> variables, PrefixMap prefixMapping) { bw = IO.wrap(out) ; vars = variables ; pmap = prefixMapping ; nodeFormatter = new NodeFormatterTTL(null, pmap) ; needOutputVars = (vars != null ) && vars.size() > 0 ; } public final void write(Binding binding) { send(binding) ; } @Override public void send(Binding binding) { try { if ( needOutputPMap ) { if ( pmap != null ) { for ( Map.Entry<String, IRI> e : pmap.getMapping().entrySet() ) { bw.write("PREFIX ") ; bw.write(e.getKey()) ; bw.write(": <") ; bw.write(e.getValue().toASCIIString()) ; bw.write("> .\n") ; } } needOutputPMap = false ; } // Is the current VARS applicable? if ( needVars(vars, binding) ) { vars = Iter.toList(binding.vars()) ; needOutputVars = true ; } if ( needOutputVars ) { // Odd special case. // No vars, empty binding. if ( binding.size() == 0 && vars.size() == 0 ) { bw.write(".\n") ; needOutputVars = false ; return ; } bw.write("VARS") ; for ( Var v2 : vars ) { bw.write(" ?") ; bw.write(v2.getVarName()) ; } bw.write(" .\n") ; needOutputVars = false ; } for ( Var v : vars ) { Node n = binding.get(v) ; if ( n == null ) { bw.write("- ") ; continue ; } // NodeFormatters should write safe bNode labels. nodeFormatter.format(bw, n) ; bw.write(" ") ; } bw.write(".\n") ; } catch (IOException ex) { throw new RiotException(ex) ; } } private static boolean needVars(List<Var> vars, Binding binding) { if ( vars == null ) return true ; for ( Var v : vars ) { if ( ! binding.contains(v) ) return true ; } return false ; } @Override public void flush() { IO.flush(bw) ; } @Override public void close() { IO.close(bw) ; } public List<Var> getVars() { return vars ; } public void setVars(List<Var> vars) { this.vars = vars ; } public PrefixMap getPrefixMap() { return pmap ; } public void setPrefixMap(PrefixMap pmap) { this.pmap = pmap ; this.needOutputPMap = true ; } }