/* Copyright 2008, 2009, 2010 by the Oxford University Computing Laboratory
This file is part of HermiT.
HermiT 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 3 of the License, or
(at your option) any later version.
HermiT 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 HermiT. If not, see <http://www.gnu.org/licenses/>.
*/
package org.semanticweb.HermiT.tableau;
import java.io.Serializable;
import org.semanticweb.HermiT.model.AtomicConcept;
import org.semanticweb.HermiT.model.AtomicRole;
import org.semanticweb.HermiT.model.Concept;
import org.semanticweb.HermiT.model.InternalDatatype;
/**
* This extension table is for use with binary and ternary assertions (not
* description graphs).
* @see ExtensionTableWithFullIndex
*/
public class ExtensionTableWithTupleIndexes extends ExtensionTable {
private static final long serialVersionUID=-684536236157965372L;
protected final TupleIndex[] m_tupleIndexes;
protected final Object[] m_auxiliaryTuple;
public ExtensionTableWithTupleIndexes(Tableau tableau,int tupleArity,boolean needsDependencySets,TupleIndex[] tupleIndexes) {
super(tableau,tupleArity,needsDependencySets);
m_tupleIndexes=tupleIndexes;
m_auxiliaryTuple=new Object[m_tupleArity];
}
public int sizeInMemory() {
int size=m_tupleTable.sizeInMemory();
for (int i=m_tupleIndexes.length-1;i>=0;--i)
size+=m_tupleIndexes[i].sizeInMemoy();
return size;
}
public boolean addTuple(Object[] tuple,DependencySet dependencySet,boolean isCore) {
if (m_tableauMonitor!=null)
m_tableauMonitor.addFactStarted(tuple,isCore);
if (isTupleActive(tuple) && (m_tableau.m_needsThingExtension || !AtomicConcept.THING.equals(tuple[0])) && (m_tableau.m_needsRDFSLiteralExtension || !InternalDatatype.RDFS_LITERAL.equals(tuple[0]))) {
int firstFreeTupleIndex=m_tupleTable.getFirstFreeTupleIndex();
int addTupleIndex=m_tupleIndexes[0].addTuple(tuple,firstFreeTupleIndex);
if (addTupleIndex==firstFreeTupleIndex) {
for (int index=1;index<m_tupleIndexes.length;index++)
m_tupleIndexes[index].addTuple(tuple,addTupleIndex);
m_tupleTable.addTuple(tuple);
m_dependencySetManager.setDependencySet(addTupleIndex,dependencySet);
m_coreManager.setCore(addTupleIndex,isCore);
m_afterDeltaNewTupleIndex=m_tupleTable.getFirstFreeTupleIndex();
if (m_tableauMonitor!=null)
m_tableauMonitor.addFactFinished(tuple,isCore,true);
postAdd(tuple,dependencySet,addTupleIndex,isCore);
return true;
}
if (isCore && !m_coreManager.isCore(addTupleIndex)) {
m_coreManager.addCore(addTupleIndex);
Object dlPredicateObject=tuple[0];
if (dlPredicateObject instanceof Concept)
m_tableau.m_existentialExpansionStrategy.assertionCoreSet((Concept)dlPredicateObject,(Node)tuple[1]);
else if (dlPredicateObject instanceof AtomicRole)
m_tableau.m_existentialExpansionStrategy.assertionCoreSet((AtomicRole)dlPredicateObject,(Node)tuple[1],(Node)tuple[2]);
}
}
if (m_tableauMonitor!=null)
m_tableauMonitor.addFactFinished(tuple,isCore,false);
return false;
}
public boolean containsTuple(Object[] tuple) {
int tupleIndex=m_tupleIndexes[0].getTupleIndex(tuple);
return tupleIndex!=-1 && isTupleActive(tupleIndex);
}
public DependencySet getDependencySet(Object[] tuple) {
int tupleIndex=m_tupleIndexes[0].getTupleIndex(tuple);
// If the tuple is not in the tuple table, we'll get back -1; then, there is no dependency set.
if (tupleIndex==-1)
return null;
else
return m_dependencySetManager.getDependencySet(tupleIndex);
}
public boolean isCore(Object[] tuple) {
int tupleIndex=m_tupleIndexes[0].getTupleIndex(tuple);
if (tupleIndex==-1)
return false;
else
return m_coreManager.isCore(tupleIndex);
}
public Retrieval createRetrieval(int[] bindingPositions,Object[] bindingsBuffer,Object[] tupleBuffer,boolean ownsBuffers,View extensionView) {
TupleIndex selectedTupleIndex=null;
int boundPrefixSizeInSelected=0;
for (int index=m_tupleIndexes.length-1;index>=0;--index) {
int[] indexingSequence=m_tupleIndexes[index].getIndexingSequence();
int boundPrefixSize=0;
for (int position=0;position<indexingSequence.length;position++)
if (bindingPositions[indexingSequence[position]]!=-1)
boundPrefixSize++;
else
break;
if (boundPrefixSize>boundPrefixSizeInSelected) {
selectedTupleIndex=m_tupleIndexes[index];
boundPrefixSizeInSelected=boundPrefixSize;
}
}
if (selectedTupleIndex==null)
return new UnindexedRetrieval(bindingPositions,bindingsBuffer,tupleBuffer,ownsBuffers,extensionView);
else
return new IndexedRetrieval(selectedTupleIndex,bindingPositions,bindingsBuffer,tupleBuffer,ownsBuffers,extensionView);
}
protected void removeTuple(int tupleIndex) {
m_tupleTable.retrieveTuple(m_auxiliaryTuple,tupleIndex);
for (int index=m_tupleIndexes.length-1;index>=0;--index)
m_tupleIndexes[index].removeTuple(m_auxiliaryTuple);
postRemove(m_auxiliaryTuple,tupleIndex);
}
public void clear() {
super.clear();
for (int index=m_tupleIndexes.length-1;index>=0;--index)
m_tupleIndexes[index].clear();
}
protected class IndexedRetrieval extends TupleIndex.TupleIndexRetrieval implements Retrieval,Serializable {
private static final long serialVersionUID=2180748099314801734L;
protected final int[] m_bindingPositions;
protected final Object[] m_tupleBuffer;
protected final boolean m_ownsBuffers;
protected final ExtensionTable.View m_extensionView;
protected final boolean m_checkTupleSelection;
protected DependencySet m_dependencySet;
protected boolean m_isCore;
protected int m_firstTupleIndex;
protected int m_afterLastTupleIndex;
public IndexedRetrieval(TupleIndex tupleIndex,int[] bindingPositions,Object[] bindingsBuffer,Object[] tupleBuffer,boolean ownsBuffers,View extensionView) {
super(tupleIndex,bindingsBuffer,createSelectionArray(bindingPositions,tupleIndex.m_indexingSequence));
m_ownsBuffers=ownsBuffers;
m_bindingPositions=bindingPositions;
m_extensionView=extensionView;
m_tupleBuffer=tupleBuffer;
int numberOfBoundPositions=0;
for (int index=m_bindingPositions.length-1;index>=0;--index)
if (m_bindingPositions[index]!=-1)
numberOfBoundPositions++;
m_checkTupleSelection=(numberOfBoundPositions>m_selectionIndices.length);
}
public ExtensionTable getExtensionTable() {
return ExtensionTableWithTupleIndexes.this;
}
public ExtensionTable.View getExtensionView() {
return m_extensionView;
}
public void clear() {
if (m_ownsBuffers) {
for (int index=m_bindingsBuffer.length-1;index>=0;--index)
m_bindingsBuffer[index]=null;
for (int index=m_tupleBuffer.length-1;index>=0;--index)
m_tupleBuffer[index]=null;
}
}
public int[] getBindingPositions() {
return m_bindingPositions;
}
public Object[] getBindingsBuffer() {
return m_bindingsBuffer;
}
public Object[] getTupleBuffer() {
return m_tupleBuffer;
}
public DependencySet getDependencySet() {
return m_dependencySet;
}
public boolean isCore() {
return m_isCore;
}
public void open() {
switch (m_extensionView) {
case EXTENSION_THIS:
m_firstTupleIndex=0;
m_afterLastTupleIndex=m_afterExtensionThisTupleIndex;
break;
case EXTENSION_OLD:
m_firstTupleIndex=0;
m_afterLastTupleIndex=m_afterExtensionOldTupleIndex;
break;
case DELTA_OLD:
m_firstTupleIndex=m_afterExtensionOldTupleIndex;
m_afterLastTupleIndex=m_afterExtensionThisTupleIndex;
break;
case TOTAL:
m_firstTupleIndex=0;
m_afterLastTupleIndex=m_afterDeltaNewTupleIndex;
break;
}
super.open();
while (!afterLast()) {
int tupleIndex=getCurrentTupleIndex();
if (m_firstTupleIndex<=tupleIndex && tupleIndex<m_afterLastTupleIndex) {
m_tupleTable.retrieveTuple(m_tupleBuffer,tupleIndex);
if (isTupleValid()) {
m_dependencySet=m_dependencySetManager.getDependencySet(tupleIndex);
m_isCore=m_coreManager.isCore(tupleIndex);
return;
}
}
super.next();
}
}
public void next() {
super.next();
while (!afterLast()) {
int tupleIndex=getCurrentTupleIndex();
if (m_firstTupleIndex<=tupleIndex && tupleIndex<m_afterLastTupleIndex) {
m_tupleTable.retrieveTuple(m_tupleBuffer,tupleIndex);
if (isTupleValid()) {
m_dependencySet=m_dependencySetManager.getDependencySet(tupleIndex);
m_isCore=m_coreManager.isCore(tupleIndex);
return;
}
}
super.next();
}
}
protected boolean isTupleValid() {
if (!ExtensionTableWithTupleIndexes.this.isTupleActive(m_tupleBuffer))
return false;
if (m_checkTupleSelection)
for (int index=m_bindingPositions.length-1;index>=0;--index)
if (m_bindingPositions[index]!=-1 && !m_tupleBuffer[index].equals(m_bindingsBuffer[m_bindingPositions[index]]))
return false;
return true;
}
}
protected static int[] createSelectionArray(int[] bindingPositions,int[] indexingSequence) {
int boundPrefixLength=0;
for (int index=0;index<indexingSequence.length;index++)
if (bindingPositions[indexingSequence[index]]!=-1)
boundPrefixLength++;
else
break;
int[] selection=new int[boundPrefixLength];
for (int index=0;index<boundPrefixLength;index++)
selection[index]=bindingPositions[indexingSequence[index]];
return selection;
}
}