/* 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.blocking; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.Set; import org.semanticweb.HermiT.model.AtomicConcept; import org.semanticweb.HermiT.model.AtomicRole; import org.semanticweb.HermiT.model.Concept; import org.semanticweb.HermiT.model.DataRange; import org.semanticweb.HermiT.tableau.ExtensionTable; import org.semanticweb.HermiT.tableau.Node; import org.semanticweb.HermiT.tableau.NodeType; import org.semanticweb.HermiT.tableau.Tableau; public class ValidatedSingleDirectBlockingChecker implements DirectBlockingChecker,Serializable { private static final long serialVersionUID=9093753046859877016L; protected final SetFactory<AtomicConcept> m_atomicConceptsSetFactory=new SetFactory<AtomicConcept>(); protected final SetFactory<AtomicRole> m_atomicRolesSetFactory=new SetFactory<AtomicRole>(); protected final List<AtomicConcept> m_atomicConceptsBuffer=new ArrayList<AtomicConcept>(); protected final List<AtomicRole> m_atomicRolesBuffer=new ArrayList<AtomicRole>(); protected final boolean m_hasInverses; protected Tableau m_tableau; protected ExtensionTable.Retrieval m_binaryTableSearch1Bound; protected ExtensionTable.Retrieval m_ternaryTableSearch12Bound; public ValidatedSingleDirectBlockingChecker(boolean hasInverses) { m_hasInverses=hasInverses; } public void initialize(Tableau tableau) { m_tableau=tableau; m_binaryTableSearch1Bound=tableau.getExtensionManager().getBinaryExtensionTable().createRetrieval(new boolean[] { false,true },ExtensionTable.View.TOTAL); m_ternaryTableSearch12Bound=tableau.getExtensionManager().getTernaryExtensionTable().createRetrieval(new boolean[] { false,true,true },ExtensionTable.View.TOTAL); } public void clear() { m_atomicConceptsSetFactory.clearNonpermanent(); m_atomicRolesSetFactory.clearNonpermanent(); m_binaryTableSearch1Bound.clear(); m_ternaryTableSearch12Bound.clear(); } public boolean isBlockedBy(Node blocker,Node blocked) { boolean isBlockedBy= !blocker.isBlocked() && blocker.getNodeType()==NodeType.TREE_NODE && blocked.getNodeType()==NodeType.TREE_NODE && ((ValidatedSingleBlockingObject)blocker.getBlockingObject()).getAtomicConceptsLabel()==((ValidatedSingleBlockingObject)blocked.getBlockingObject()).getAtomicConceptsLabel(); return isBlockedBy; } public int blockingHashCode(Node node) { return ((ValidatedSingleBlockingObject)node.getBlockingObject()).m_blockingRelevantHashCode; } public boolean canBeBlocker(Node node) { Node parent=node.getParent(); return node.getNodeType()==NodeType.TREE_NODE && (!m_hasInverses || node.getParent().getNodeType()==NodeType.TREE_NODE || parent.getNodeType()==NodeType.GRAPH_NODE); } public boolean canBeBlocked(Node node) { Node parent=node.getParent(); return node.getNodeType()==NodeType.TREE_NODE && (!m_hasInverses || node.getParent().getNodeType()==NodeType.TREE_NODE || parent.getNodeType()==NodeType.GRAPH_NODE); } public boolean hasBlockingInfoChanged(Node node) { return ((ValidatedSingleBlockingObject)node.getBlockingObject()).m_hasChangedForBlocking; } public void clearBlockingInfoChanged(Node node) { ((ValidatedSingleBlockingObject)node.getBlockingObject()).m_hasChangedForBlocking=false; } public boolean hasChangedSinceValidation(Node node) { return ((ValidatedSingleBlockingObject)node.getBlockingObject()).m_hasChangedForValidation; } public void setHasChangedSinceValidation(Node node, boolean hasChanged) { ((ValidatedSingleBlockingObject)node.getBlockingObject()).m_hasChangedForValidation=hasChanged; } public void nodeInitialized(Node node) { if (node.getBlockingObject()==null) node.setBlockingObject(new ValidatedSingleBlockingObject(node)); ((ValidatedSingleBlockingObject)node.getBlockingObject()).initialize(); } public void nodeDestroyed(Node node) { ((ValidatedSingleBlockingObject)node.getBlockingObject()).destroy(); } public Node assertionAdded(Concept concept,Node node,boolean isCore) { ((ValidatedSingleBlockingObject)node.getBlockingObject()).addConcept(concept, isCore); return (concept instanceof AtomicConcept && isCore)?node:null; } public Node assertionRemoved(Concept concept, Node node, boolean isCore) { ((ValidatedSingleBlockingObject) node.getBlockingObject()).removeConcept(concept, isCore); return (concept instanceof AtomicConcept && isCore)?node:null; } public Node assertionAdded(DataRange range,Node node,boolean isCore) { return null; } public Node assertionRemoved(DataRange range,Node node,boolean isCore) { return null; } public Node assertionAdded(AtomicRole atomicRole,Node nodeFrom,Node nodeTo,boolean isCore) { return null; } public Node assertionRemoved(AtomicRole atomicRole,Node nodeFrom,Node nodeTo,boolean isCore) { return null; } public Node nodesMerged(Node mergeFrom,Node mergeInto) { return null; } public Node nodesUnmerged(Node mergeFrom,Node mergeInto) { return null; } protected Set<AtomicConcept> fetchAtomicConceptsLabel(Node node,boolean onlyCore) { m_atomicConceptsBuffer.clear(); m_binaryTableSearch1Bound.getBindingsBuffer()[1]=node; m_binaryTableSearch1Bound.open(); Object[] tupleBuffer=m_binaryTableSearch1Bound.getTupleBuffer(); while (!m_binaryTableSearch1Bound.afterLast()) { Object concept=tupleBuffer[0]; if (concept instanceof AtomicConcept) { if (!onlyCore || m_binaryTableSearch1Bound.isCore()) { m_atomicConceptsBuffer.add((AtomicConcept)concept); } } m_binaryTableSearch1Bound.next(); } Set<AtomicConcept> result=m_atomicConceptsSetFactory.getSet(m_atomicConceptsBuffer); m_atomicConceptsBuffer.clear(); return result; } protected Set<AtomicRole> fetchAtomicRolesLabel(Node nodeFrom,Node nodeTo,boolean onlyCore) { m_atomicRolesBuffer.clear(); m_ternaryTableSearch12Bound.getBindingsBuffer()[1] = nodeFrom; m_ternaryTableSearch12Bound.getBindingsBuffer()[2] = nodeTo; m_ternaryTableSearch12Bound.open(); Object[] tupleBuffer = m_ternaryTableSearch12Bound.getTupleBuffer(); while (!m_ternaryTableSearch12Bound.afterLast()) { Object atomicRole = tupleBuffer[0]; if (atomicRole instanceof AtomicRole && (!onlyCore || m_binaryTableSearch1Bound.isCore())) { m_atomicRolesBuffer.add((AtomicRole) atomicRole); } m_ternaryTableSearch12Bound.next(); } Set<AtomicRole> result = m_atomicRolesSetFactory.getSet(m_atomicRolesBuffer); m_atomicRolesBuffer.clear(); return result; } public BlockingSignature getBlockingSignatureFor(Node node) { return new ValidatedBlockingSignature(this,node); } public class ValidatedSingleBlockingObject implements ValidatedBlockingObject { protected final Node m_node; protected boolean m_hasChangedForBlocking; protected boolean m_hasChangedForValidation; protected Set<AtomicConcept> m_blockingRelevantLabel; protected Set<AtomicConcept> m_fullAtomicConceptsLabel; protected Set<AtomicRole> m_fullFromParentLabel; protected Set<AtomicRole> m_fullToParentLabel; protected int m_blockingRelevantHashCode; public boolean m_blockViolatesParentConstraints=false; public boolean m_hasAlreadyBeenChecked=false; public ValidatedSingleBlockingObject(Node node) { m_node=node; } public void initialize() { m_blockingRelevantLabel=null; m_blockingRelevantHashCode=0; m_fullAtomicConceptsLabel=null; m_fullFromParentLabel=null; m_fullToParentLabel=null; m_hasChangedForBlocking=true; m_hasChangedForValidation=true; } public void destroy() { if (m_blockingRelevantLabel!=null) { m_atomicConceptsSetFactory.removeReference(m_blockingRelevantLabel); m_blockingRelevantLabel=null; } if (m_fullAtomicConceptsLabel!=null) { m_atomicConceptsSetFactory.removeReference(m_fullAtomicConceptsLabel); m_fullAtomicConceptsLabel=null; } if (m_fullFromParentLabel!=null) { m_atomicRolesSetFactory.removeReference(m_fullFromParentLabel); m_fullFromParentLabel=null; } if (m_fullToParentLabel!=null) { m_atomicRolesSetFactory.removeReference(m_fullToParentLabel); m_fullToParentLabel=null; } } public Set<AtomicConcept> getAtomicConceptsLabel() { if (m_blockingRelevantLabel==null) { m_blockingRelevantLabel=ValidatedSingleDirectBlockingChecker.this.fetchAtomicConceptsLabel(m_node,true); m_atomicConceptsSetFactory.addReference(m_blockingRelevantLabel); } return m_blockingRelevantLabel; } public void addConcept(Concept concept, boolean isCore) { // for validation purposes not only the core and atomic concept changes matter m_hasChangedForValidation=true; if (concept instanceof AtomicConcept) { // relevant for blocking if (m_fullAtomicConceptsLabel!=null) { // invalidate, recompute real label later if necessary m_atomicConceptsSetFactory.removeReference(m_fullAtomicConceptsLabel); m_fullAtomicConceptsLabel=null; } if (isCore) { if (m_blockingRelevantLabel!=null) { // invalidate, recompute real label later if necessary m_atomicConceptsSetFactory.removeReference(m_blockingRelevantLabel); m_blockingRelevantLabel=null; } m_blockingRelevantHashCode+=concept.hashCode(); m_hasChangedForBlocking=true; } } } public void removeConcept(Concept concept, boolean isCore) { // for validation purposes not only the core and atomicConcept // changes matter m_hasChangedForValidation = true; if (concept instanceof AtomicConcept) { if (m_fullAtomicConceptsLabel != null) { // invalidate, recompute real label later if necessary m_atomicConceptsSetFactory.removeReference(m_fullAtomicConceptsLabel); m_fullAtomicConceptsLabel = null; } if (isCore) { if (m_blockingRelevantLabel != null) { // invalidate, recompute real label later if necessary m_atomicConceptsSetFactory.removeReference(m_blockingRelevantLabel); m_blockingRelevantLabel = null; } m_blockingRelevantHashCode-=concept.hashCode(); m_hasChangedForBlocking=true; } } } public Set<AtomicConcept> getFullAtomicConceptsLabel() { if (m_fullAtomicConceptsLabel==null) { m_fullAtomicConceptsLabel=ValidatedSingleDirectBlockingChecker.this.fetchAtomicConceptsLabel(m_node,false); m_atomicConceptsSetFactory.addReference(m_fullAtomicConceptsLabel); } return m_fullAtomicConceptsLabel; } public Set<AtomicRole> getFullFromParentLabel() { if (m_hasChangedForValidation || m_fullFromParentLabel==null) { m_fullFromParentLabel=ValidatedSingleDirectBlockingChecker.this.fetchAtomicRolesLabel(m_node.getParent(),m_node,false); m_atomicRolesSetFactory.addReference(m_fullFromParentLabel); } return m_fullFromParentLabel; } public Set<AtomicRole> getFullToParentLabel() { if (m_hasChangedForValidation || m_fullToParentLabel==null) { m_fullToParentLabel=ValidatedSingleDirectBlockingChecker.this.fetchAtomicRolesLabel(m_node,m_node.getParent(),false); m_atomicRolesSetFactory.addReference(m_fullToParentLabel); } return m_fullToParentLabel; } public void setBlockViolatesParentConstraints(boolean violates) { m_blockViolatesParentConstraints=violates; } public void setHasAlreadyBeenChecked(boolean hasBeenChecked) { m_hasAlreadyBeenChecked=hasBeenChecked; } public boolean hasAlreadyBeenChecked() { return m_hasAlreadyBeenChecked; } public boolean blockViolatesParentConstraints() { return m_blockViolatesParentConstraints; } } protected static class ValidatedBlockingSignature extends BlockingSignature { protected final Set<AtomicConcept> m_blockingRelevantConceptsLabel; protected final Set<AtomicConcept> m_fullAtomicConceptsLabel; protected final Set<AtomicConcept> m_parentFullAtomicConceptsLabel; protected final Set<AtomicRole> m_fromParentLabel; protected final Set<AtomicRole> m_toParentLabel; protected final int m_hashCode; public ValidatedBlockingSignature(ValidatedSingleDirectBlockingChecker checker,Node node) { ValidatedSingleBlockingObject nodeBlockingObject=(ValidatedSingleBlockingObject)node.getBlockingObject(); m_blockingRelevantConceptsLabel=nodeBlockingObject.getAtomicConceptsLabel(); m_fullAtomicConceptsLabel=nodeBlockingObject.getFullAtomicConceptsLabel(); m_parentFullAtomicConceptsLabel=((ValidatedSingleBlockingObject)node.getParent().getBlockingObject()).getFullAtomicConceptsLabel(); m_fromParentLabel=nodeBlockingObject.getFullFromParentLabel(); m_toParentLabel=nodeBlockingObject.getFullToParentLabel(); m_hashCode=m_blockingRelevantConceptsLabel.hashCode(); checker.m_atomicConceptsSetFactory.makePermanent(m_fullAtomicConceptsLabel); checker.m_atomicConceptsSetFactory.makePermanent(m_parentFullAtomicConceptsLabel); checker.m_atomicRolesSetFactory.makePermanent(m_fromParentLabel); checker.m_atomicRolesSetFactory.makePermanent(m_toParentLabel); } public boolean blocksNode(Node node) { ValidatedSingleBlockingObject nodeBlockingObject = (ValidatedSingleBlockingObject) node.getBlockingObject(); return nodeBlockingObject.getAtomicConceptsLabel() == m_blockingRelevantConceptsLabel; } public int hashCode() { return m_hashCode; } public boolean equals(Object that) { if (this==that) return true; if (!(that instanceof ValidatedBlockingSignature)) return false; ValidatedBlockingSignature thatSignature=(ValidatedBlockingSignature)that; return m_blockingRelevantConceptsLabel==thatSignature.m_blockingRelevantConceptsLabel && m_fullAtomicConceptsLabel==thatSignature.m_fullAtomicConceptsLabel && m_parentFullAtomicConceptsLabel==thatSignature.m_parentFullAtomicConceptsLabel && m_fromParentLabel==thatSignature.m_fromParentLabel && m_toParentLabel==thatSignature.m_toParentLabel; } } public static interface ValidatedBlockingObject { public void initialize(); public void destroy(); public Set<AtomicConcept> getAtomicConceptsLabel(); public void addConcept(Concept concept, boolean isCore); public void removeConcept(Concept concept, boolean isCore); public Set<AtomicConcept> getFullAtomicConceptsLabel(); public Set<AtomicRole> getFullFromParentLabel(); public Set<AtomicRole> getFullToParentLabel(); public void setBlockViolatesParentConstraints(boolean violates); public void setHasAlreadyBeenChecked(boolean hasBeenChecked); public boolean hasAlreadyBeenChecked(); public boolean blockViolatesParentConstraints(); } }