/*
* 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.pfunction.library;
import java.util.Collection ;
import java.util.List ;
import java.util.Set ;
import org.apache.jena.graph.Graph ;
import org.apache.jena.graph.Node ;
import org.apache.jena.sparql.core.Var ;
import org.apache.jena.sparql.engine.ExecutionContext ;
import org.apache.jena.sparql.engine.QueryIterator ;
import org.apache.jena.sparql.engine.binding.Binding ;
import org.apache.jena.sparql.engine.binding.BindingFactory ;
import org.apache.jena.sparql.engine.iterator.QueryIterConcat ;
import org.apache.jena.sparql.pfunction.PropFuncArg ;
import org.apache.jena.sparql.pfunction.PropFuncArgType ;
import org.apache.jena.sparql.pfunction.PropertyFunctionEval ;
import org.apache.jena.sparql.util.graph.GraphList ;
/** Base class for list realted operations */
public abstract class ListBase extends PropertyFunctionEval
{
private PropFuncArgType objFuncArgType ;
public ListBase(PropFuncArgType objFuncArgType)
{
super(PropFuncArgType.PF_ARG_SINGLE, objFuncArgType) ;
}
/** If the subject is a list (well, at least not an unbound variable), dispatch to execOneList
* else dispatch to one of object a var, a list or a node.
*/
@Override
final
public QueryIterator execEvaluated(Binding binding, PropFuncArg argSubject, Node predicate, PropFuncArg argObject, ExecutionContext execCxt)
{
Node listNode = argSubject.getArg() ;
if ( !Var.isVar(listNode) )
// Subject bound or constant
return execOneList(binding, listNode, predicate, argObject, execCxt) ;
// Subject unbound.
Var listVar = Var.alloc(listNode) ;
return listUnboundSubject(binding, listVar, predicate, argObject, execCxt) ;
}
private QueryIterator listUnboundSubject(Binding binding, Var listVar, Node predicate, PropFuncArg argObject,
ExecutionContext execCxt)
{
// Object?
if ( argObject.isList() )
{
List<Node> objectArgs = argObject.getArgList() ;
return execObjectList(binding, listVar, predicate, objectArgs, execCxt) ;
}
Node obj = argObject.getArg() ;
if ( Var.isVar(obj))
{
Graph graph = execCxt.getActiveGraph() ;
Set<Node> x = GraphList.findAllLists(graph) ;
return allLists(binding, x, listVar, obj, argObject, execCxt) ;
}
// {
// // Gulp. Subject unbound. Object unbound. BFI: Find all lists; work hard.
// Set<Node> x = GraphList.findAllLists(graph) ;
// QueryIterConcat qIter = new QueryIterConcat(execCxt) ;
// for ( Node n : x )
// {
// Binding b = new Binding1(binding, listVar, n) ;
// QueryIterator q = execOneList(b, n, predicate, argObject, execCxt) ;
// qIter.add(q) ;
// }
// return qIter ;
// }
// Subject unbound. Object a bound node.
return execObjectBound(binding, listVar, predicate, obj, execCxt) ;
}
protected QueryIterator allLists(Binding binding, Collection<Node> x, Var listVar, Node predicate, PropFuncArg argObject, ExecutionContext execCxt)
{
// BFI: Find all lists; work hard.
QueryIterConcat qIter = new QueryIterConcat(execCxt) ;
for ( Node n : x )
{
Binding b = BindingFactory.binding(binding, listVar, n) ;
QueryIterator q = execOneList(b, n, predicate, argObject, execCxt) ;
qIter.add(q) ;
}
return qIter ;
}
/**
* @param binding current binding as input
* @param listVar a variable.
* @param predicate the predicate used to invoke this property function
* @param object the object of the property function
* @param execCxt Execution context
* @return QueryIterator
*/
protected abstract
QueryIterator execObjectBound(Binding binding, Var listVar, Node predicate, Node object,
ExecutionContext execCxt) ;
/**
* @param binding current binding as input
* @param listVar a variable.
* @param predicate the predicate used to invoke this property function
* @param objectArgs the object of the property function
* @param execCxt Execution context
* @return QueryIterator
*/
protected abstract
QueryIterator execObjectList(Binding binding, Var listVar, Node predicate, List<Node> objectArgs,
ExecutionContext execCxt) ;
/** Dispatch when the subject is a list - also used when subject and object all unbound
* after finding all lists.
* @param binding current binding as input
* @param listNode the list; maybe a variable.
* @param predicate the predicate used to invoke this property function
* @param object the object of the property function; maybe a variable
* @param execCxt Execution context
* @return QueryIterator
*/
protected abstract
QueryIterator execOneList(Binding binding, Node listNode, Node predicate, PropFuncArg object, ExecutionContext execCxt) ;
}