
org.apache.jena.sparql.engine.binding.BindingInputStream Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jena-arq Show documentation
Show all versions of jena-arq Show documentation
ARQ is a SPARQL 1.1 query engine for Apache Jena
/*
* 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 static org.apache.jena.riot.tokens.TokenType.DOT ;
import static org.apache.jena.riot.tokens.TokenType.IRI ;
import static org.apache.jena.riot.tokens.TokenType.PREFIXED_NAME ;
import java.io.InputStream ;
import java.util.ArrayList ;
import java.util.Collections ;
import java.util.Iterator ;
import java.util.List ;
import org.apache.jena.atlas.iterator.IteratorSlotted ;
import org.apache.jena.atlas.lib.Closeable ;
import org.apache.jena.graph.Node ;
import org.apache.jena.graph.NodeFactory ;
import org.apache.jena.iri.IRI ;
import org.apache.jena.riot.lang.LabelToNode ;
import org.apache.jena.riot.lang.LangEngine ;
import org.apache.jena.riot.out.NodeFmtLib ;
import org.apache.jena.riot.system.* ;
import org.apache.jena.riot.tokens.Token ;
import org.apache.jena.riot.tokens.TokenType ;
import org.apache.jena.riot.tokens.Tokenizer ;
import org.apache.jena.riot.tokens.TokenizerFactory ;
import org.apache.jena.sparql.core.Var ;
/** Language for reading in a stream of bindings.
* See BindingIO
*
* Summary:
*
* - Directives:
*
* - VARS - list of variables.
* - PREFIX
*
*
* - Lines of RDF terms (Turtle, no triple-quoted strings)
* - Items on line align with last VARS declaration
* - * for "same as last row"
* - - for "undef"
*
*/
public class BindingInputStream extends LangEngine implements Iterator, Closeable
{
// In effect, multiple Inheritance.
// We implementation-inherit from LangEngine(no public methods)
// and also IteratorTuples (redirecting calls to be object)
private final IteratorTuples iter ;
public BindingInputStream(InputStream in)
{
this(TokenizerFactory.makeTokenizerUTF8(in)) ;
}
public BindingInputStream(Tokenizer tokenizer)
{
this(tokenizer, profile()) ;
}
static ParserProfile profile()
{
// Don't do anything with IRIs.
Prologue prologue = new Prologue(PrefixMapFactory.createForInput(), IRIResolver.createNoResolve()) ;
ErrorHandler handler = ErrorHandlerFactory.getDefaultErrorHandler() ;
FactoryRDF factory = RiotLib.factoryRDF(LabelToNode.createUseLabelAsGiven()) ;
ParserProfile profile = new ParserProfileBase(prologue, handler, factory) ;
// Include safe bNode labels.
return profile ;
}
/** Create an RDF Tuples parser.
* No need to pass in a buffered InputStream; the code
* will do it's own buffering.
*/
private BindingInputStream(Tokenizer tokenizer, ParserProfile profile)
{
super(tokenizer, profile) ;
iter = new IteratorTuples() ;
}
@Override
public boolean hasNext()
{
return iter.hasNext() ;
}
@Override
public Binding next()
{
return iter.next() ;
}
@Override
public void remove()
{ iter.remove() ; }
public List vars()
{ return Collections.unmodifiableList(iter.vars) ; }
class IteratorTuples extends IteratorSlotted
{
private Binding lastLine ;
List vars = new ArrayList<>() ;
// Process any directive immediately.
public IteratorTuples()
{
directives() ;
}
private void directives()
{
while ( lookingAt(TokenType.KEYWORD) )
{
Token t = nextToken() ;
if ( t.getImage().equalsIgnoreCase("VARS") )
{
directiveVars() ;
continue ;
}
if ( t.getImage().equalsIgnoreCase("PREFIX") )
{
directivePrefix() ;
continue ;
}
}
}
@Override
protected Binding moveToNext()
{
directives() ;
BindingMap binding = BindingFactory.create() ;
int i = 0 ;
while( ! lookingAt(TokenType.DOT) )
{
if ( i >= vars.size() )
exception(peekToken(), "Too many items in a line. Expected "+vars.size()) ;
Var v = vars.get(i) ;
Token token = nextToken() ;
if ( ! token.hasType(TokenType.MINUS ) )
{
Node n ;
// One case; VARS line then *
if ( token.hasType(TokenType.STAR ) || ( token.isCtlCode() && token.getCntrlCode() == -1 ) )
n = lastLine.get(v) ;
else if ( token.hasType(TokenType.BNODE) )
n = NodeFactory.createBlankNode(NodeFmtLib.decodeBNodeLabel(token.getImage())) ;
else
n = profile.create(null, token) ;
binding.add(v, n) ;
}
i++ ;
}
if ( eof() )
exception(peekToken(), "Line does not end with a DOT") ;
Token dot = nextToken() ;
if ( i != vars.size() )
{
Var v = vars.get(vars.size()-1) ;
exception(dot, "Too many items in a line. Expected "+vars.size()) ;
}
lastLine = binding ;
return binding ;
}
@Override
protected boolean hasMore()
{
return moreTokens() ;
}
private void directiveVars()
{
vars.clear() ;
while (! eof() && ! lookingAt(DOT) )
{
Token t = nextToken() ;
if ( ! t.hasType(TokenType.VAR) )
exception(t, "VARS requires a list of variables (found '"+t+"')") ;
Var v = Var.alloc(t.getImage()) ;
vars.add(v) ;
}
nextToken() ; // DOT
}
private void directivePrefix()
{
if ( ! lookingAt(PREFIXED_NAME) )
exception(peekToken(), "PREFIX requires a prefix (found '"+peekToken()+"')") ;
if ( peekToken().getImage2().length() != 0 )
exception(peekToken(), "PREFIX requires a prefix and no suffix (found '"+peekToken()+"')") ;
String prefix = peekToken().getImage() ;
nextToken() ;
if ( ! lookingAt(IRI) )
exception(peekToken(), "@prefix requires an IRI (found '"+peekToken()+"')") ;
String iriStr = peekToken().getImage() ;
IRI iri = profile.makeIRI(iriStr, currLine, currCol) ;
profile.getPrologue().getPrefixMap().add(prefix, iri) ;
nextToken() ;
expect("PREFIX directive not terminated by a dot", DOT) ;
}
}
@Override
public void close() { super.tokens.close() ; }
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy