/* 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.AtomicNegationConcept; import org.semanticweb.HermiT.model.AtomicNegationDataRange; import org.semanticweb.HermiT.model.AtomicRole; import org.semanticweb.HermiT.model.Inequality; import org.semanticweb.HermiT.model.InternalDatatype; import org.semanticweb.HermiT.model.LiteralConcept; import org.semanticweb.HermiT.model.LiteralDataRange; import org.semanticweb.HermiT.model.NegatedAtomicRole; import org.semanticweb.HermiT.monitor.TableauMonitor; /** * An instance of this class is notified by extension tables when tuples are added. This class then * detects whether the addition of a tuple caused a clash or not. Clashes are detected as soon as * offending assertions are added to the extensions (i.e., they do not depend on delta-new). * This is so for performance reasons: we want to detect a clash ASAP so that we can save * ourselves unnecessary work. */ public final class ClashManager implements Serializable { private static final long serialVersionUID = 3533809151139695892L; protected static final LiteralDataRange NOT_RDFS_LITERAL=InternalDatatype.RDFS_LITERAL.getNegation(); protected final ExtensionManager m_extensionManager; protected final ExtensionTable.Retrieval m_ternaryExtensionTableSearch01Bound; protected final TableauMonitor m_tableauMonitor; protected final Object[] m_binaryAuxiliaryTuple; protected final Object[] m_ternaryAuxiliaryTuple; protected final UnionDependencySet m_binaryUnionDependencySet; public ClashManager(Tableau tableau) { m_extensionManager=tableau.m_extensionManager; m_ternaryExtensionTableSearch01Bound=m_extensionManager.m_ternaryExtensionTable.createRetrieval(new boolean[] { true,true,false },ExtensionTable.View.TOTAL); m_tableauMonitor=tableau.m_tableauMonitor; m_binaryAuxiliaryTuple=new Object[2]; m_ternaryAuxiliaryTuple=new Object[3]; m_binaryUnionDependencySet=new UnionDependencySet(2); } public void clear() { m_ternaryExtensionTableSearch01Bound.clear(); m_binaryAuxiliaryTuple[0]=null; m_binaryAuxiliaryTuple[1]=null; m_ternaryAuxiliaryTuple[0]=null; m_ternaryAuxiliaryTuple[1]=null; m_ternaryAuxiliaryTuple[2]=null; m_binaryUnionDependencySet.m_dependencySets[0]=null; m_binaryUnionDependencySet.m_dependencySets[1]=null; } public void tupleAdded(ExtensionTable extensionTable,Object[] tuple,DependencySet dependencySet,boolean isCore) { Object dlPredicateObject=tuple[0]; Node node0=(Node)tuple[1]; if (AtomicConcept.NOTHING.equals(dlPredicateObject) || NOT_RDFS_LITERAL.equals(dlPredicateObject) || (Inequality.INSTANCE.equals(dlPredicateObject) && tuple[1]==tuple[2])) { if (m_tableauMonitor!=null) m_tableauMonitor.clashDetectionStarted(tuple); m_extensionManager.setClash(dependencySet); if (m_tableauMonitor!=null) m_tableauMonitor.clashDetectionFinished(tuple); } else if ((dlPredicateObject instanceof InternalDatatype) || (dlPredicateObject instanceof AtomicNegationDataRange && ((AtomicNegationDataRange)dlPredicateObject).getNegatedDataRange() instanceof InternalDatatype) || (dlPredicateObject instanceof AtomicConcept && node0.m_numberOfNegatedAtomicConcepts>0) || (dlPredicateObject instanceof AtomicNegationConcept && node0.m_numberOfPositiveAtomicConcepts>0)) { m_binaryAuxiliaryTuple[0]=dlPredicateObject instanceof LiteralDataRange ? ((LiteralDataRange)dlPredicateObject).getNegation() : ((LiteralConcept)dlPredicateObject).getNegation(); m_binaryAuxiliaryTuple[1]=node0; if (extensionTable.containsTuple(m_binaryAuxiliaryTuple)) { m_binaryUnionDependencySet.m_dependencySets[0]=dependencySet; m_binaryUnionDependencySet.m_dependencySets[1]=extensionTable.getDependencySet(m_binaryAuxiliaryTuple); if (m_tableauMonitor!=null) m_tableauMonitor.clashDetectionStarted(tuple,m_binaryAuxiliaryTuple); m_extensionManager.setClash(m_binaryUnionDependencySet); if (m_tableauMonitor!=null) m_tableauMonitor.clashDetectionFinished(tuple,m_binaryAuxiliaryTuple); } } else if ((dlPredicateObject instanceof AtomicRole && node0.m_numberOfNegatedRoleAssertions>0) || (dlPredicateObject instanceof NegatedAtomicRole)) { Object searchPredicate; if (dlPredicateObject instanceof AtomicRole) searchPredicate=NegatedAtomicRole.create((AtomicRole)dlPredicateObject); else searchPredicate=((NegatedAtomicRole)dlPredicateObject).getNegatedAtomicRole(); m_ternaryAuxiliaryTuple[0]=searchPredicate; m_ternaryAuxiliaryTuple[1]=node0; m_ternaryAuxiliaryTuple[2]=tuple[2]; if (extensionTable.containsTuple(m_ternaryAuxiliaryTuple)) { m_binaryUnionDependencySet.m_dependencySets[0]=dependencySet; m_binaryUnionDependencySet.m_dependencySets[1]=extensionTable.getDependencySet(m_ternaryAuxiliaryTuple); if (m_tableauMonitor!=null) m_tableauMonitor.clashDetectionStarted(tuple,m_ternaryAuxiliaryTuple); m_extensionManager.setClash(m_binaryUnionDependencySet); if (m_tableauMonitor!=null) m_tableauMonitor.clashDetectionFinished(tuple,m_ternaryAuxiliaryTuple); } else if (!((Node)tuple[2]).getNodeType().isAbstract()) { // If the second node is not abstract (i.e., if it is concrete), then we may need to generate inequalities. m_ternaryAuxiliaryTuple[0]=Inequality.INSTANCE; m_ternaryAuxiliaryTuple[1]=tuple[2]; m_binaryUnionDependencySet.m_dependencySets[0]=dependencySet; m_ternaryExtensionTableSearch01Bound.getBindingsBuffer()[0]=searchPredicate; m_ternaryExtensionTableSearch01Bound.getBindingsBuffer()[1]=tuple[1]; m_ternaryExtensionTableSearch01Bound.open(); Object[] tupleBuffer=m_ternaryExtensionTableSearch01Bound.getTupleBuffer(); while (!m_ternaryExtensionTableSearch01Bound.afterLast()) { assert !((Node)tupleBuffer[2]).getNodeType().isAbstract(); m_ternaryAuxiliaryTuple[2]=tupleBuffer[2]; m_binaryUnionDependencySet.m_dependencySets[1]=m_ternaryExtensionTableSearch01Bound.getDependencySet(); if (m_tableauMonitor!=null) m_tableauMonitor.clashDetectionStarted(tuple,tupleBuffer); // Warning: the following call is reentrant. That is, we might be currently processing // an addition on the extension manager, during which we then add another tuple. // In general, such calls do not work. The added tuple is, however, quite simple, // so such reentrant calls are OK. In order to prevent the reentrancy check in // ExtensionManager, we go directly to the ternary table. m_extensionManager.m_ternaryExtensionTable.addTuple(m_ternaryAuxiliaryTuple,m_binaryUnionDependencySet,true); if (m_tableauMonitor!=null) m_tableauMonitor.clashDetectionFinished(tuple,tupleBuffer); m_ternaryExtensionTableSearch01Bound.next(); } } } } }