package org.semanticweb.HermiT.datalog; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import org.semanticweb.HermiT.model.Atom; import org.semanticweb.HermiT.model.DLClause; import org.semanticweb.HermiT.model.Term; import org.semanticweb.HermiT.model.Variable; import org.semanticweb.HermiT.tableau.DLClauseEvaluator; import org.semanticweb.HermiT.tableau.DLClauseEvaluator.Worker; import org.semanticweb.HermiT.tableau.DependencySet; import org.semanticweb.HermiT.tableau.ExtensionTable; import org.semanticweb.HermiT.tableau.ExtensionTable.View; import org.semanticweb.HermiT.tableau.HyperresolutionManager; import org.semanticweb.HermiT.tableau.Node; public class ConjunctiveQuery { protected final DatalogEngine m_datalogEngine; protected final Atom[] m_queryAtoms; protected final Term[] m_answerTerms; protected final Term[] m_resultBuffer; protected final OneEmptyTupleRetrieval m_firstRetrieval; protected final QueryResultCollector[] m_queryResultCollector; protected final Worker[] m_workers; public ConjunctiveQuery(DatalogEngine datalogEngine,Atom[] queryAtoms,Term[] answerTerms) { if (!datalogEngine.materialize()) throw new IllegalStateException("The supplied DL ontology is unsatisfiable."); m_datalogEngine=datalogEngine; m_queryAtoms=queryAtoms; m_answerTerms=answerTerms; m_resultBuffer=answerTerms.clone(); m_firstRetrieval=new OneEmptyTupleRetrieval(); m_queryResultCollector=new QueryResultCollector[1]; HyperresolutionManager.BodyAtomsSwapper swapper=new HyperresolutionManager.BodyAtomsSwapper(DLClause.create(new Atom[0],queryAtoms)); DLClause queryDLClause=swapper.getSwappedDLClause(0); QueryCompiler queryCompiler=new QueryCompiler(this,queryDLClause,answerTerms,datalogEngine.m_termsToNodes,datalogEngine.m_nodesToTerms,m_resultBuffer,m_queryResultCollector,m_firstRetrieval); m_workers=new Worker[queryCompiler.m_workers.size()]; queryCompiler.m_workers.toArray(m_workers); } public DatalogEngine getDatalogEngine() { return m_datalogEngine; } public int getNumberOfQUeryAtoms() { return m_queryAtoms.length; } public Atom getQueryAtom(int atomIndex) { return m_queryAtoms[atomIndex]; } public int getNumberOfAnswerTerms() { return m_answerTerms.length; } public Term getAnswerTerm(int termIndex) { return m_answerTerms[termIndex]; } public void evaluate(QueryResultCollector queryResultCollector) { try { m_queryResultCollector[0]=queryResultCollector; m_firstRetrieval.open(); int programCounter=0; while (programCounter<m_workers.length) programCounter=m_workers[programCounter].execute(programCounter); } finally { m_queryResultCollector[0]=null; } } protected static final class OneEmptyTupleRetrieval implements ExtensionTable.Retrieval { protected static final int[] s_noBindings=new int[0]; protected static final Object[] s_noObjects=new Object[0]; protected boolean m_afterLast; public OneEmptyTupleRetrieval() { m_afterLast=true; } public ExtensionTable getExtensionTable() { throw new UnsupportedOperationException(); } public View getExtensionView() { return View.TOTAL; } public void clear() { throw new UnsupportedOperationException(); } public int[] getBindingPositions() { return s_noBindings; } public Object[] getBindingsBuffer() { return s_noObjects; } public Object[] getTupleBuffer() { return s_noObjects; } public DependencySet getDependencySet() { throw new UnsupportedOperationException(); } public boolean isCore() { return false; } public void open() { m_afterLast=false; } public boolean afterLast() { return m_afterLast; } public int getCurrentTupleIndex() { return m_afterLast ? -1 : 0; } public void next() { m_afterLast=true; } } public static class QueryAnswerCallback implements Worker { protected final ConjunctiveQuery m_conjunctiveQuery; protected final Map<Node,Term> m_nodesToTerms; protected final Term[] m_resultBuffer; protected final QueryResultCollector[] m_queryResultCollector; protected final int[][] m_copyAnswers; protected final Object[] m_valuesBuffer; public QueryAnswerCallback(ConjunctiveQuery conjunctiveQuery,Map<Node,Term> nodesToTerms,Term[] resultBuffer,QueryResultCollector[] queryResultCollector,int[][] copyAnswers,Object[] valuesBuffer) { m_conjunctiveQuery=conjunctiveQuery; m_nodesToTerms=nodesToTerms; m_resultBuffer=resultBuffer; m_queryResultCollector=queryResultCollector; m_copyAnswers=copyAnswers; m_valuesBuffer=valuesBuffer; } public int execute(int programCounter) { for (int copyIndex=m_copyAnswers.length-1;copyIndex>=0;--copyIndex) m_resultBuffer[m_copyAnswers[copyIndex][1]]=m_nodesToTerms.get((Node)m_valuesBuffer[m_copyAnswers[copyIndex][0]]); m_queryResultCollector[0].processResult(m_conjunctiveQuery,m_resultBuffer); return programCounter+1; } public String toString() { return "Call query consumer"; } } protected static final class QueryCompiler extends DLClauseEvaluator.ConjunctionCompiler { protected final ConjunctiveQuery m_conjunctiveQuery; protected final Term[] m_answerTerms; protected final Map<Node,Term> m_nodesToTerms; protected final Term[] m_resultBuffer; protected final QueryResultCollector[] m_queryResultCollector; public QueryCompiler(ConjunctiveQuery conjunctiveQuery,DLClause queryDLClause,Term[] answerTerms,Map<Term,Node> termsToNodes,Map<Node,Term> nodesToTerms,Term[] resultBuffer,QueryResultCollector[] queryResultCollector,ExtensionTable.Retrieval oneEmptyTupleRetrieval) { super(new DLClauseEvaluator.BufferSupply(),new DLClauseEvaluator.ValuesBufferManager(Collections.singleton(queryDLClause),termsToNodes),null,conjunctiveQuery.m_datalogEngine.m_extensionManager,queryDLClause.getBodyAtoms(),getAnswerVariables(answerTerms)); m_conjunctiveQuery=conjunctiveQuery; m_answerTerms=answerTerms; m_nodesToTerms=nodesToTerms; m_resultBuffer=resultBuffer; m_queryResultCollector=queryResultCollector; generateCode(0,oneEmptyTupleRetrieval); } protected void compileHeads() { List<int[]> copyAnswers=new ArrayList<int[]>(); for (int index=0;index<m_answerTerms.length;++index) { Term answerTerm=m_answerTerms[index]; if (answerTerm instanceof Variable) { int answerVariableIndex=m_variables.indexOf(answerTerm); copyAnswers.add(new int[] { answerVariableIndex,index }); } } m_workers.add(new QueryAnswerCallback(m_conjunctiveQuery,m_nodesToTerms,m_resultBuffer,m_queryResultCollector,copyAnswers.toArray(new int[copyAnswers.size()][]),m_valuesBufferManager.m_valuesBuffer)); } protected static List<Variable> getAnswerVariables(Term[] answerTerms) { List<Variable> result=new ArrayList<Variable>(); for (Term answerTerm : answerTerms) if (answerTerm instanceof Variable) result.add((Variable)answerTerm); return result; } } }