/** * File: $HeadURL: https://hdt-java.googlecode.com/svn/trunk/hdt-jena/src/org/rdfhdt/hdtjena/solver/HDTSolverLib.java $ * Revision: $Rev: 197 $ * Last modified: $Date: 2013-04-12 19:39:33 +0100 (vie, 12 abr 2013) $ * Last modified by: $Author: mario.arias $ * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * * Contacting the authors: * Mario Arias: mario.arias@deri.org * Javier D. Fernandez: jfergar@infor.uva.es * Miguel A. Martinez-Prieto: migumar2@infor.uva.es */ package org.rdfhdt.hdtjena.solver; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.function.Function; import java.util.function.Predicate; import org.apache.jena.atlas.iterator.Iter; import org.apache.jena.atlas.lib.Tuple; import org.apache.jena.graph.Node; import org.apache.jena.graph.Triple; import org.apache.jena.shared.PrefixMapping; import org.apache.jena.sparql.core.BasicPattern; 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.util.iterator.Filter; import org.rdfhdt.hdt.enums.TripleComponentRole; import org.rdfhdt.hdtjena.HDTGraph; import org.rdfhdt.hdtjena.NodeDictionary; import org.rdfhdt.hdtjena.bindings.BindingHDTId; import org.rdfhdt.hdtjena.bindings.BindingHDTNode; import org.rdfhdt.hdtjena.bindings.HDTId; import org.rdfhdt.hdtjena.util.Abortable; import org.rdfhdt.hdtjena.util.IterAbortable; import org.rdfhdt.hdtjena.util.VarAppearance; /** Utilities used within the HDT BGP solver : local HDT store */ public class HDTSolverLib { public static long numBGPs; protected static QueryIterator execute(HDTGraph graph, BasicPattern pattern, QueryIterator input, Predicate<Tuple<HDTId>> filter, ExecutionContext execCxt) { numBGPs++; Iterator<BindingHDTId> chain = Iter.map(input, HDTSolverLib.convFromBinding(graph.getNodeDictionary(), execCxt)) ; List<Abortable> killList = new ArrayList<Abortable>() ; // Compute appearances of variables Map<Var, VarAppearance> mapVar = new HashMap<Var, VarAppearance>(); for ( Triple triplePattern : pattern ) { addVarAppearance(mapVar, triplePattern.getSubject(), TripleComponentRole.SUBJECT); // addVarAppearance(mapVar, triplePattern.getPredicate(), TripleComponentRole.PREDICATE); addVarAppearance(mapVar, triplePattern.getObject(), TripleComponentRole.OBJECT); } for ( Triple triplePattern : pattern ) { chain = solve(graph, triplePattern, chain, filter, mapVar, execCxt) ; chain = IterAbortable.makeAbortable(chain, killList) ; } // Need to make sure the bindings here point to parent. Iterator<Binding> iterBinding = converter.convert(graph.getNodeDictionary(), chain) ; // "input" will be closed by QueryIterHDT but is otherwise unused. // "killList" will be aborted on timeout. return new QueryIterHDT(iterBinding, killList, input, execCxt) ; } private static void addVarAppearance(Map<Var, VarAppearance> mapVar, Node node, TripleComponentRole role) { if(node.isVariable()) { Var v = NodeDictionary.asVar(node); VarAppearance varAp = mapVar.get(v); if(varAp==null) { varAp = new VarAppearance(); mapVar.put(v, varAp); } varAp.set(role); } } private static Iterator<BindingHDTId> solve(HDTGraph graph, Triple tuple, Iterator<BindingHDTId> chain, Predicate<Tuple<HDTId>> filter, Map<Var, VarAppearance> mapVar, ExecutionContext execCxt) { return new StageMatchTripleID(graph, chain, tuple, execCxt, mapVar) ; } private static HDTId getID(Node n, NodeDictionary dict, PrefixMapping prefixMapping) { int id = dict.getIntID(n, prefixMapping, TripleComponentRole.SUBJECT); if(id>0) { return new HDTId(id, TripleComponentRole.SUBJECT, dict); } id = dict.getIntID(n, prefixMapping, TripleComponentRole.PREDICATE); if(id>0) { return new HDTId(id, TripleComponentRole.PREDICATE, dict); } id = dict.getIntID(n, prefixMapping, TripleComponentRole.OBJECT); if(id>0) { return new HDTId(id, TripleComponentRole.OBJECT, dict); } return null; // NOT FOUND } // Conversions public interface ConvertHDTIdToNode { Iterator<Binding> convert(NodeDictionary dictionary, Iterator<BindingHDTId> iterBindingIds) ; } // Transform : BindingHDTId ==> Binding private static Function<BindingHDTId, Binding> convToBinding(final NodeDictionary dictionary) { return new Function<BindingHDTId, Binding>() { @Override public Binding apply(BindingHDTId bindingIds) { return new BindingHDTNode(bindingIds); } } ; } public final static ConvertHDTIdToNode converter = new ConvertHDTIdToNode(){ @Override public Iterator<Binding> convert(NodeDictionary dictionary, Iterator<BindingHDTId> iterBindingIds) { return Iter.map(iterBindingIds, convToBinding(dictionary)) ; } } ; public static Iterator<BindingHDTId> convertToIds(Iterator<Binding> iterBindings, NodeDictionary dictionary, ExecutionContext ctx) { return Iter.map(iterBindings, convFromBinding(dictionary, ctx)) ; } public static Iterator<Binding> convertToNodes(Iterator<BindingHDTId> iterBindingIds, NodeDictionary dictionary) { return Iter.map(iterBindingIds, convToBinding(dictionary)) ; } // Transform : Binding ==> BindingHDTId public static Function<Binding, BindingHDTId> convFromBinding(final NodeDictionary dictionary, final ExecutionContext ctx) { return new Function<Binding, BindingHDTId>() { PrefixMapping mapping = NodeDictionary.getMapping(ctx); @Override public BindingHDTId apply(Binding binding) { if ( binding instanceof BindingHDTNode ) return ((BindingHDTNode)binding).getBindingId() ; BindingHDTId b = new BindingHDTId(binding) ; // and copy over, getting HDTIds. Iterator<Var> vars = binding.vars() ; for ( ; vars.hasNext() ; ) { Var v = vars.next() ; Node n = binding.get(v) ; if ( n == null ) // Variable mentioned in the binding but not actually defined. // Can occur with BindingProject continue ; HDTId id = getID(n, dictionary, mapping); // Even put "does not exist" if it is null. b.put(v, id) ; } return b ; } }; } }