/* 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 PairWiseDirectBlockingChecker implements DirectBlockingChecker,Serializable { private static final long serialVersionUID=-8296420442452625109L; protected final SetFactory<AtomicConcept> m_atomicConceptsSetFactory; protected final SetFactory<AtomicRole> m_atomicRolesSetFactory; protected final List<AtomicConcept> m_atomicConceptsBuffer; protected final List<AtomicRole> m_atomicRolesBuffer; protected Tableau m_tableau; protected ExtensionTable.Retrieval m_binaryTableSearch1Bound; protected ExtensionTable.Retrieval m_ternaryTableSearch12Bound; public PairWiseDirectBlockingChecker() { m_atomicConceptsSetFactory=new SetFactory<AtomicConcept>(); m_atomicRolesSetFactory=new SetFactory<AtomicRole>(); m_atomicConceptsBuffer=new ArrayList<AtomicConcept>(); m_atomicRolesBuffer=new ArrayList<AtomicRole>(); } 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) { PairWiseBlockingObject blockerObject=(PairWiseBlockingObject)blocker.getBlockingObject(); PairWiseBlockingObject blockedObject=(PairWiseBlockingObject)blocked.getBlockingObject(); return !blocker.isBlocked() && blocker.getNodeType()==NodeType.TREE_NODE && blocked.getNodeType()==NodeType.TREE_NODE && blockerObject.getAtomicConceptsLabel()==blockedObject.getAtomicConceptsLabel() && ((PairWiseBlockingObject)blocker.getParent().getBlockingObject()).getAtomicConceptsLabel()==((PairWiseBlockingObject)blocked.getParent().getBlockingObject()).getAtomicConceptsLabel() && blockerObject.getFromParentLabel()==blockedObject.getFromParentLabel() && blockerObject.getToParentLabel()==blockedObject.getToParentLabel(); } public int blockingHashCode(Node node) { PairWiseBlockingObject nodeObject=(PairWiseBlockingObject)node.getBlockingObject(); return nodeObject.m_atomicConceptsLabelHashCode+ ((PairWiseBlockingObject)node.getParent().getBlockingObject()).m_atomicConceptsLabelHashCode+ nodeObject.m_fromParentLabelHashCode+ nodeObject.m_toParentLabelHashCode; } public boolean canBeBlocker(Node node) { Node parent=node.getParent(); return node.getNodeType()==NodeType.TREE_NODE && (parent.getNodeType()==NodeType.TREE_NODE || parent.getNodeType()==NodeType.GRAPH_NODE); } public boolean canBeBlocked(Node node) { Node parent=node.getParent(); return node.getNodeType()==NodeType.TREE_NODE && (parent.getNodeType()==NodeType.TREE_NODE || parent.getNodeType()==NodeType.GRAPH_NODE); } public boolean hasBlockingInfoChanged(Node node) { return ((PairWiseBlockingObject)node.getBlockingObject()).m_hasChanged; } public void clearBlockingInfoChanged(Node node) { ((PairWiseBlockingObject)node.getBlockingObject()).m_hasChanged=false; } public void nodeInitialized(Node node) { if (node.getBlockingObject()==null) node.setBlockingObject(new PairWiseBlockingObject(node)); ((PairWiseBlockingObject)node.getBlockingObject()).initialize(); } public void nodeDestroyed(Node node) { ((PairWiseBlockingObject)node.getBlockingObject()).destroy(); } public Node assertionAdded(Concept concept,Node node,boolean isCore) { if (concept instanceof AtomicConcept) { ((PairWiseBlockingObject)node.getBlockingObject()).addAtomicConcept((AtomicConcept)concept); return node; } else return null; } public Node assertionRemoved(Concept concept,Node node,boolean isCore) { if (concept instanceof AtomicConcept) { ((PairWiseBlockingObject)node.getBlockingObject()).removeAtomicConcept((AtomicConcept)concept); return node; } else return 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) { if (nodeFrom.isParentOf(nodeTo)) { ((PairWiseBlockingObject)nodeTo.getBlockingObject()).addToFromParentLabel(atomicRole); return nodeTo; } else if (nodeTo.isParentOf(nodeFrom)) { ((PairWiseBlockingObject)nodeFrom.getBlockingObject()).addToToParentLabel(atomicRole); return nodeFrom; } else { // If the previous two tests fail, then the added assertion represents a relation between // root nodes or a back-link to the root node. Such assertions are not relevant for blocking; // hence, neither node should be marked as changed. return null; } } public Node assertionRemoved(AtomicRole atomicRole,Node nodeFrom,Node nodeTo,boolean isCore) { if (nodeFrom.isParentOf(nodeTo)) { ((PairWiseBlockingObject)nodeTo.getBlockingObject()).removeFromFromParentLabel(atomicRole); return nodeTo; } else if (nodeTo.isParentOf(nodeFrom)) { ((PairWiseBlockingObject)nodeFrom.getBlockingObject()).removeFromToParentLabel(atomicRole); return nodeFrom; } else { // If the previous two tests fail, then the removed assertion represents a relation between // root nodes or a back-link to the root node. Such assertions are not relevant for blocking; // hence, neither node should be marked as changed. return null; } } public Node nodesMerged(Node mergeFrom,Node mergeInto) { return null; } public Node nodesUnmerged(Node mergeFrom,Node mergeInto) { return null; } public BlockingSignature getBlockingSignatureFor(Node node) { return new PairWiseBlockingSignature(this,node); } protected Set<AtomicConcept> fetchAtomicConceptsLabel(Node node) { 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) m_atomicConceptsBuffer.add((AtomicConcept)concept); m_binaryTableSearch1Bound.next(); } Set<AtomicConcept> result=m_atomicConceptsSetFactory.getSet(m_atomicConceptsBuffer); m_atomicConceptsBuffer.clear(); return result; } public Set<AtomicRole> fetchEdgeLabel(Node nodeFrom,Node nodeTo) { 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) m_atomicRolesBuffer.add((AtomicRole)atomicRole); m_ternaryTableSearch12Bound.next(); } Set<AtomicRole> result=m_atomicRolesSetFactory.getSet(m_atomicRolesBuffer); m_atomicRolesBuffer.clear(); return result; } public boolean hasChangedSinceValidation(Node node) { return false; } public void setHasChangedSinceValidation(Node node,boolean hasChanged) { // do nothing } protected final class PairWiseBlockingObject implements Serializable { private static final long serialVersionUID=-5439737072100509531L; protected final Node m_node; protected boolean m_hasChanged; protected Set<AtomicConcept> m_atomicConceptsLabel; protected int m_atomicConceptsLabelHashCode; protected Set<AtomicRole> m_fromParentLabel; protected int m_fromParentLabelHashCode; protected Set<AtomicRole> m_toParentLabel; protected int m_toParentLabelHashCode; public PairWiseBlockingObject(Node node) { m_node=node; } public void initialize() { m_atomicConceptsLabel=null; m_atomicConceptsLabelHashCode=0; m_fromParentLabel=null; m_fromParentLabelHashCode=0; m_toParentLabel=null; m_toParentLabelHashCode=0; m_hasChanged=true; } public void destroy() { if (m_atomicConceptsLabel!=null) { m_atomicConceptsSetFactory.removeReference(m_atomicConceptsLabel); m_atomicConceptsLabel=null; } if (m_fromParentLabel!=null) { m_atomicRolesSetFactory.removeReference(m_fromParentLabel); m_fromParentLabel=null; } if (m_toParentLabel!=null) { m_atomicRolesSetFactory.removeReference(m_toParentLabel); m_toParentLabel=null; } } public Set<AtomicConcept> getAtomicConceptsLabel() { if (m_atomicConceptsLabel==null) { m_atomicConceptsLabel=PairWiseDirectBlockingChecker.this.fetchAtomicConceptsLabel(m_node); m_atomicConceptsSetFactory.addReference(m_atomicConceptsLabel); } return m_atomicConceptsLabel; } public void addAtomicConcept(AtomicConcept atomicConcept) { if (m_atomicConceptsLabel!=null) { m_atomicConceptsSetFactory.removeReference(m_atomicConceptsLabel); m_atomicConceptsLabel=null; } m_atomicConceptsLabelHashCode+=atomicConcept.hashCode(); m_hasChanged=true; } public void removeAtomicConcept(AtomicConcept atomicConcept) { if (m_atomicConceptsLabel!=null) { m_atomicConceptsSetFactory.removeReference(m_atomicConceptsLabel); m_atomicConceptsLabel=null; } m_atomicConceptsLabelHashCode-=atomicConcept.hashCode(); m_hasChanged=true; } public Set<AtomicRole> getFromParentLabel() { if (m_fromParentLabel==null) { m_fromParentLabel=fetchEdgeLabel(m_node.getParent(),m_node); m_atomicRolesSetFactory.addReference(m_fromParentLabel); } return m_fromParentLabel; } protected void addToFromParentLabel(AtomicRole atomicRole) { if (m_fromParentLabel!=null) { m_atomicRolesSetFactory.removeReference(m_fromParentLabel); m_fromParentLabel=null; } m_fromParentLabelHashCode+=atomicRole.hashCode(); m_hasChanged=true; } protected void removeFromFromParentLabel(AtomicRole atomicRole) { if (m_fromParentLabel!=null) { m_atomicRolesSetFactory.removeReference(m_fromParentLabel); m_fromParentLabel=null; } m_fromParentLabelHashCode-=atomicRole.hashCode(); m_hasChanged=true; } public Set<AtomicRole> getToParentLabel() { if (m_toParentLabel==null) { m_toParentLabel=fetchEdgeLabel(m_node,m_node.getParent()); m_atomicRolesSetFactory.addReference(m_toParentLabel); } return m_toParentLabel; } protected void addToToParentLabel(AtomicRole atomicRole) { if (m_toParentLabel!=null) { m_atomicRolesSetFactory.removeReference(m_toParentLabel); m_toParentLabel=null; } m_toParentLabelHashCode+=atomicRole.hashCode(); m_hasChanged=true; } protected void removeFromToParentLabel(AtomicRole atomicRole) { if (m_toParentLabel!=null) { m_atomicRolesSetFactory.removeReference(m_toParentLabel); m_toParentLabel=null; } m_toParentLabelHashCode-=atomicRole.hashCode(); m_hasChanged=true; } } protected static class PairWiseBlockingSignature extends BlockingSignature implements Serializable { private static final long serialVersionUID=4697990424058632618L; protected final Set<AtomicConcept> m_atomicConceptLabel; protected final Set<AtomicConcept> m_parentAtomicConceptLabel; protected final Set<AtomicRole> m_fromParentLabel; protected final Set<AtomicRole> m_toParentLabel; protected final int m_hashCode; public PairWiseBlockingSignature(PairWiseDirectBlockingChecker checker,Node node) { PairWiseBlockingObject nodeBlockingObject=(PairWiseBlockingObject)node.getBlockingObject(); m_atomicConceptLabel=nodeBlockingObject.getAtomicConceptsLabel(); m_parentAtomicConceptLabel=((PairWiseBlockingObject)node.getParent().getBlockingObject()).getAtomicConceptsLabel(); m_fromParentLabel=nodeBlockingObject.getFromParentLabel(); m_toParentLabel=nodeBlockingObject.getToParentLabel(); m_hashCode= m_atomicConceptLabel.hashCode()+ m_parentAtomicConceptLabel.hashCode()+ m_fromParentLabel.hashCode()+ m_toParentLabel.hashCode(); checker.m_atomicConceptsSetFactory.makePermanent(m_atomicConceptLabel); checker.m_atomicConceptsSetFactory.makePermanent(m_parentAtomicConceptLabel); checker.m_atomicRolesSetFactory.makePermanent(m_fromParentLabel); checker.m_atomicRolesSetFactory.makePermanent(m_toParentLabel); } public boolean blocksNode(Node node) { PairWiseBlockingObject nodeBlockingObject=(PairWiseBlockingObject)node.getBlockingObject(); return nodeBlockingObject.getAtomicConceptsLabel()==m_atomicConceptLabel && ((PairWiseBlockingObject)node.getParent().getBlockingObject()).getAtomicConceptsLabel()==m_parentAtomicConceptLabel && nodeBlockingObject.getFromParentLabel()==m_fromParentLabel && nodeBlockingObject.getToParentLabel()==m_toParentLabel; } public int hashCode() { return m_hashCode; } public boolean equals(Object that) { if (this==that) return true; if (!(that instanceof PairWiseBlockingSignature)) return false; PairWiseBlockingSignature thatSignature=(PairWiseBlockingSignature)that; return m_atomicConceptLabel==thatSignature.m_atomicConceptLabel && m_parentAtomicConceptLabel==thatSignature.m_parentAtomicConceptLabel && m_fromParentLabel==thatSignature.m_fromParentLabel && m_toParentLabel==thatSignature.m_toParentLabel; } } }