/* 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.model;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import org.semanticweb.HermiT.Prefixes;
/**
* Represents a DL ontology as a set of rules.
*/
public class DLOntology implements Serializable {
private static final long serialVersionUID=3189937959595369812L;
protected static final String CRLF=System.getProperty("line.separator");
protected final String m_ontologyIRI;
protected final Set<DLClause> m_dlClauses;
protected final Set<Atom> m_positiveFacts;
protected final Set<Atom> m_negativeFacts;
protected final boolean m_hasInverseRoles;
protected final boolean m_hasAtMostRestrictions;
protected final boolean m_hasNominals;
protected final boolean m_hasDatatypes;
protected final boolean m_isHorn;
protected final Set<AtomicConcept> m_allAtomicConcepts;
protected final int m_numberOfExternalConcepts;
protected final Set<AtomicRole> m_allAtomicObjectRoles;
protected final Set<Role> m_allComplexObjectRoles;
protected final Set<AtomicRole> m_allAtomicDataRoles;
protected final Set<DatatypeRestriction> m_allUnknownDatatypeRestrictions;
protected final Set<String> m_definedDatatypeIRIs;
protected final Set<Individual> m_allIndividuals;
protected final Set<DescriptionGraph> m_allDescriptionGraphs;
protected final Map<AtomicRole,Map<Individual,Set<Constant>>> m_dataPropertyAssertions;
public DLOntology(String ontologyIRI,Set<DLClause> dlClauses,Set<Atom> positiveFacts,Set<Atom> negativeFacts, Set<AtomicConcept> atomicConcepts,
Set<AtomicRole> atomicObjectRoles,Set<Role> allComplexObjectRoles,Set<AtomicRole> atomicDataRoles,
Set<DatatypeRestriction> allUnknownDatatypeRestrictions,Set<String> definedDatatypeIRIs,Set<Individual> individuals,
boolean hasInverseRoles,boolean hasAtMostRestrictions,boolean hasNominals,boolean hasDatatypes) {
m_ontologyIRI=ontologyIRI;
m_dlClauses=dlClauses;
m_positiveFacts=positiveFacts;
m_negativeFacts=negativeFacts;
m_hasInverseRoles=hasInverseRoles;
m_hasAtMostRestrictions=hasAtMostRestrictions;
m_hasNominals=hasNominals;
m_hasDatatypes=hasDatatypes;
if (atomicConcepts==null)
m_allAtomicConcepts=new TreeSet<AtomicConcept>(AtomicConceptComparator.INSTANCE);
else
m_allAtomicConcepts=atomicConcepts;
int numberOfExternalConcepts=0;
for (AtomicConcept c : m_allAtomicConcepts)
if (!Prefixes.isInternalIRI(c.getIRI()))
numberOfExternalConcepts++;
m_numberOfExternalConcepts=numberOfExternalConcepts;
if (atomicObjectRoles==null)
m_allAtomicObjectRoles=new TreeSet<AtomicRole>(AtomicRoleComparator.INSTANCE);
else
m_allAtomicObjectRoles=atomicObjectRoles;
if (allComplexObjectRoles==null)
m_allComplexObjectRoles=new HashSet<Role>();
else
m_allComplexObjectRoles=allComplexObjectRoles;
if (atomicDataRoles==null)
m_allAtomicDataRoles=new TreeSet<AtomicRole>(AtomicRoleComparator.INSTANCE);
else
m_allAtomicDataRoles=atomicDataRoles;
if (allUnknownDatatypeRestrictions==null)
m_allUnknownDatatypeRestrictions=new HashSet<DatatypeRestriction>();
else
m_allUnknownDatatypeRestrictions=allUnknownDatatypeRestrictions;
if (definedDatatypeIRIs==null)
m_definedDatatypeIRIs=new HashSet<String>();
else
m_definedDatatypeIRIs=definedDatatypeIRIs;
if (individuals==null)
m_allIndividuals=new TreeSet<Individual>(IndividualComparator.INSTANCE);
else
m_allIndividuals=individuals;
m_allDescriptionGraphs=new HashSet<DescriptionGraph>();
boolean isHorn=true;
for (DLClause dlClause : m_dlClauses) {
if (dlClause.getHeadLength()>1)
isHorn=false;
for (int bodyIndex=dlClause.getBodyLength()-1;bodyIndex>=0;--bodyIndex) {
DLPredicate dlPredicate=dlClause.getBodyAtom(bodyIndex).getDLPredicate();
addDLPredicate(dlPredicate);
}
for (int headIndex=dlClause.getHeadLength()-1;headIndex>=0;--headIndex) {
DLPredicate dlPredicate=dlClause.getHeadAtom(headIndex).getDLPredicate();
addDLPredicate(dlPredicate);
}
}
m_isHorn=isHorn;
m_dataPropertyAssertions=new HashMap<AtomicRole,Map<Individual,Set<Constant>>>();
for (Atom atom : m_positiveFacts) {
addDLPredicate(atom.getDLPredicate());
for (int i=0;i<atom.getArity();++i) {
Term argument=atom.getArgument(i);
if (argument instanceof Individual)
m_allIndividuals.add((Individual)argument);
}
if (atom.getArity()==2) {
Object possibleConstant=atom.getArgument(1);
if (possibleConstant instanceof Constant) {
// We have a data role assertion, so we store it into the approrpiate arrays
Individual sourceIndividual=(Individual)atom.getArgument(0);
assert atom.getDLPredicate() instanceof AtomicRole;
AtomicRole atomicRole=(AtomicRole)atom.getDLPredicate();
Map<Individual,Set<Constant>> individualsToConstants;
if (m_dataPropertyAssertions.containsKey(atomicRole))
individualsToConstants=m_dataPropertyAssertions.get(atomicRole);
else {
individualsToConstants=new HashMap<Individual,Set<Constant>>();
m_dataPropertyAssertions.put(atomicRole,individualsToConstants);
}
Set<Constant> constants;
if (individualsToConstants.containsKey(sourceIndividual))
constants=individualsToConstants.get(sourceIndividual);
else {
constants=new HashSet<Constant>();
individualsToConstants.put(sourceIndividual,constants);
}
constants.add((Constant)possibleConstant);
}
}
}
for (Atom atom : m_negativeFacts) {
addDLPredicate(atom.getDLPredicate());
for (int i=0;i<atom.getArity();++i) {
Term argument=atom.getArgument(i);
if (argument instanceof Individual)
m_allIndividuals.add((Individual)argument);
}
}
}
protected void addDLPredicate(DLPredicate dlPredicate) {
if (dlPredicate instanceof AtomicConcept)
m_allAtomicConcepts.add((AtomicConcept)dlPredicate);
else if (dlPredicate instanceof AtLeastConcept) {
LiteralConcept literalConcept=((AtLeastConcept)dlPredicate).getToConcept();
if (literalConcept instanceof AtomicConcept)
m_allAtomicConcepts.add((AtomicConcept)literalConcept);
}
else if (dlPredicate instanceof DescriptionGraph)
m_allDescriptionGraphs.add((DescriptionGraph)dlPredicate);
else if (dlPredicate instanceof ExistsDescriptionGraph)
m_allDescriptionGraphs.add(((ExistsDescriptionGraph)dlPredicate).getDescriptionGraph());
}
public String getOntologyIRI() {
return m_ontologyIRI;
}
public Set<AtomicConcept> getAllAtomicConcepts() {
return m_allAtomicConcepts;
}
public boolean containsAtomicConcept(AtomicConcept concept) {
return m_allAtomicConcepts.contains(concept);
}
public int getNumberOfExternalConcepts() {
return m_numberOfExternalConcepts;
}
public Set<AtomicRole> getAllAtomicObjectRoles() {
return m_allAtomicObjectRoles;
}
public boolean containsObjectRole(AtomicRole role) {
return m_allAtomicObjectRoles.contains(role);
}
public Set<Role> getAllComplexObjectRoles() {
return m_allComplexObjectRoles;
}
public boolean isComplexObjectRole(Role role) {
return m_allComplexObjectRoles.contains(role);
}
public Set<AtomicRole> getAllAtomicDataRoles() {
return m_allAtomicDataRoles;
}
public boolean containsDataRole(AtomicRole role) {
return m_allAtomicDataRoles.contains(role);
}
public Set<DatatypeRestriction> getAllUnknownDatatypeRestrictions() {
return m_allUnknownDatatypeRestrictions;
}
public Set<Individual> getAllIndividuals() {
return m_allIndividuals;
}
public boolean containsIndividual(Individual individual) {
return m_allIndividuals.contains(individual);
}
public Set<DescriptionGraph> getAllDescriptionGraphs() {
return m_allDescriptionGraphs;
}
public Set<DLClause> getDLClauses() {
return m_dlClauses;
}
public Set<Atom> getPositiveFacts() {
return m_positiveFacts;
}
public Map<AtomicRole,Map<Individual,Set<Constant>>> getDataPropertyAssertions() {
return m_dataPropertyAssertions;
}
public Set<Atom> getNegativeFacts() {
return m_negativeFacts;
}
public boolean hasInverseRoles() {
return m_hasInverseRoles;
}
public boolean hasAtMostRestrictions() {
return m_hasAtMostRestrictions;
}
public boolean hasNominals() {
return m_hasNominals;
}
public boolean hasDatatypes() {
return m_hasDatatypes;
}
public boolean hasUnknownDatatypeRestrictions() {
return !m_allUnknownDatatypeRestrictions.isEmpty();
}
public boolean isHorn() {
return m_isHorn;
}
public Set<String> getDefinedDatatypeIRIs() {
return m_definedDatatypeIRIs;
}
protected Set<AtomicConcept> getBodyOnlyAtomicConcepts() {
Set<AtomicConcept> bodyOnlyAtomicConcepts=new HashSet<AtomicConcept>(m_allAtomicConcepts);
for (DLClause dlClause : m_dlClauses)
for (int headIndex=0;headIndex<dlClause.getHeadLength();headIndex++) {
DLPredicate dlPredicate=dlClause.getHeadAtom(headIndex).getDLPredicate();
bodyOnlyAtomicConcepts.remove(dlPredicate);
if (dlPredicate instanceof AtLeastConcept)
bodyOnlyAtomicConcepts.remove(((AtLeastConcept)dlPredicate).getToConcept());
}
return bodyOnlyAtomicConcepts;
}
protected Set<AtomicRole> computeGraphAtomicRoles() {
Set<AtomicRole> graphAtomicRoles=new HashSet<AtomicRole>();
for (DescriptionGraph descriptionGraph : m_allDescriptionGraphs)
for (int edgeIndex=0;edgeIndex<descriptionGraph.getNumberOfEdges();edgeIndex++) {
DescriptionGraph.Edge edge=descriptionGraph.getEdge(edgeIndex);
graphAtomicRoles.add(edge.getAtomicRole());
}
boolean change=true;
while (change) {
change=false;
for (DLClause dlClause : m_dlClauses)
if (containsAtomicRoles(dlClause,graphAtomicRoles))
if (addAtomicRoles(dlClause,graphAtomicRoles))
change=true;
}
return graphAtomicRoles;
}
protected boolean containsAtomicRoles(DLClause dlClause,Set<AtomicRole> roles) {
for (int atomIndex=0;atomIndex<dlClause.getBodyLength();atomIndex++) {
DLPredicate dlPredicate=dlClause.getBodyAtom(atomIndex).getDLPredicate();
if (dlPredicate instanceof AtomicRole && roles.contains(dlPredicate))
return true;
}
for (int atomIndex=0;atomIndex<dlClause.getHeadLength();atomIndex++) {
DLPredicate dlPredicate=dlClause.getHeadAtom(atomIndex).getDLPredicate();
if (dlPredicate instanceof AtomicRole && roles.contains(dlPredicate))
return true;
}
return false;
}
protected boolean addAtomicRoles(DLClause dlClause,Set<AtomicRole> roles) {
boolean change=false;
for (int atomIndex=0;atomIndex<dlClause.getBodyLength();atomIndex++) {
DLPredicate dlPredicate=dlClause.getBodyAtom(atomIndex).getDLPredicate();
if (dlPredicate instanceof AtomicRole)
if (roles.add((AtomicRole)dlPredicate))
change=true;
}
for (int atomIndex=0;atomIndex<dlClause.getHeadLength();atomIndex++) {
DLPredicate dlPredicate=dlClause.getHeadAtom(atomIndex).getDLPredicate();
if (dlPredicate instanceof AtomicRole)
if (roles.add((AtomicRole)dlPredicate))
change=true;
}
return change;
}
public String toString(Prefixes prefixes) {
StringBuffer stringBuffer=new StringBuffer();
stringBuffer.append("Prefixes: [");
stringBuffer.append(CRLF);
for (Map.Entry<String,String> entry : prefixes.getPrefixIRIsByPrefixName().entrySet()) {
stringBuffer.append(" ");
stringBuffer.append(entry.getKey());
stringBuffer.append(" = <");
stringBuffer.append(entry.getValue());
stringBuffer.append('>');
stringBuffer.append(CRLF);
}
stringBuffer.append("]");
stringBuffer.append(CRLF);
stringBuffer.append("Deterministic DL-clauses: [");
stringBuffer.append(CRLF);
int numDeterministicClauses=0;
for (DLClause dlClause : m_dlClauses)
if (dlClause.getHeadLength()<=1) {
numDeterministicClauses++;
stringBuffer.append(" ");
stringBuffer.append(dlClause.toString(prefixes));
stringBuffer.append(CRLF);
}
stringBuffer.append("]");
stringBuffer.append(CRLF);
stringBuffer.append("Disjunctive DL-clauses: [");
stringBuffer.append(CRLF);
int numNondeterministicClauses=0;
int numDisjunctions=0;
for (DLClause dlClause : m_dlClauses)
if (dlClause.getHeadLength()>1) {
numNondeterministicClauses++;
numDisjunctions+=dlClause.getHeadLength();
stringBuffer.append(" ");
stringBuffer.append(dlClause.toString(prefixes));
stringBuffer.append(CRLF);
}
stringBuffer.append("]");
stringBuffer.append(CRLF);
stringBuffer.append("ABox: [");
stringBuffer.append(CRLF);
for (Atom atom : m_positiveFacts) {
stringBuffer.append(" ");
stringBuffer.append(atom.toString(prefixes));
stringBuffer.append(CRLF);
}
for (Atom atom : m_negativeFacts) {
stringBuffer.append(" !");
stringBuffer.append(atom.toString(prefixes));
stringBuffer.append(CRLF);
}
stringBuffer.append("]");
stringBuffer.append(CRLF);
stringBuffer.append("Statistics: [");
stringBuffer.append(CRLF);
stringBuffer.append(" Number of deterministic clauses: " + numDeterministicClauses);
stringBuffer.append(CRLF);
stringBuffer.append(" Number of nondeterministic clauses: " + numNondeterministicClauses);
stringBuffer.append(CRLF);
stringBuffer.append(" Number of disjunctions: " + numDisjunctions);
stringBuffer.append(CRLF);
stringBuffer.append(" Number of positive facts: " + m_positiveFacts.size());
stringBuffer.append(CRLF);
stringBuffer.append(" Number of negative facts: " + m_negativeFacts.size());
stringBuffer.append(CRLF);
stringBuffer.append("]");
return stringBuffer.toString();
}
public String getStatistics() {
return getStatistics(null,null,null);
}
protected String getStatistics(Integer numDeterministicClauses, Integer numNondeterministicClauses, Integer numDisjunctions) {
if (numDeterministicClauses==null || numNondeterministicClauses==null || numDisjunctions==null) {
numDeterministicClauses=0;
numNondeterministicClauses=0;
numDisjunctions=0;
for (DLClause dlClause : m_dlClauses) {
if (dlClause.getHeadLength()<=1)
numDeterministicClauses++;
else {
numNondeterministicClauses++;
numDisjunctions+=dlClause.getHeadLength();
}
}
}
StringBuffer stringBuffer=new StringBuffer();
stringBuffer.append("DL clauses statistics: [");
stringBuffer.append(CRLF);
stringBuffer.append(" Number of deterministic clauses: " + numDeterministicClauses);
stringBuffer.append(CRLF);
stringBuffer.append(" Number of nondeterministic clauses: " + numNondeterministicClauses);
stringBuffer.append(CRLF);
stringBuffer.append(" Overall number of disjunctions: " + numDisjunctions);
stringBuffer.append(CRLF);
stringBuffer.append(" Number of positive facts: " + m_positiveFacts.size());
stringBuffer.append(CRLF);
stringBuffer.append(" Number of negative facts: " + m_negativeFacts.size());
stringBuffer.append(CRLF);
stringBuffer.append(" Inverses: " + this.hasInverseRoles());
stringBuffer.append(CRLF);
stringBuffer.append(" At-Mosts: " + this.hasAtMostRestrictions());
stringBuffer.append(CRLF);
stringBuffer.append(" Datatypes: " + this.hasDatatypes());
stringBuffer.append(CRLF);
stringBuffer.append(" Nominals: " + this.hasNominals());
stringBuffer.append(CRLF);
stringBuffer.append(" Number of atomic concepts: " + m_allAtomicConcepts.size());
stringBuffer.append(CRLF);
stringBuffer.append(" Number of object properties: " + m_allAtomicObjectRoles.size());
stringBuffer.append(CRLF);
stringBuffer.append(" Number of data properties: " + m_allAtomicDataRoles.size());
stringBuffer.append(CRLF);
stringBuffer.append(" Number of individuals: " + m_allIndividuals.size());
stringBuffer.append(CRLF);
stringBuffer.append("]");
return stringBuffer.toString();
}
public String toString() {
return toString(Prefixes.STANDARD_PREFIXES);
}
public void save(File file) throws IOException {
OutputStream outputStream=new BufferedOutputStream(new FileOutputStream(file));
try {
save(outputStream);
}
finally {
outputStream.close();
}
}
public void save(OutputStream outputStream) throws IOException {
ObjectOutputStream objectOutputStream=new ObjectOutputStream(outputStream);
objectOutputStream.writeObject(this);
objectOutputStream.flush();
}
public static DLOntology load(InputStream inputStream) throws IOException {
try {
ObjectInputStream objectInputStream=new ObjectInputStream(inputStream);
return (DLOntology)objectInputStream.readObject();
}
catch (ClassNotFoundException e) {
IOException error=new IOException();
error.initCause(e);
throw error;
}
}
public static DLOntology load(File file) throws IOException {
InputStream inputStream=new BufferedInputStream(new FileInputStream(file));
try {
return load(inputStream);
}
finally {
inputStream.close();
}
}
public static class AtomicConceptComparator implements Serializable,Comparator<AtomicConcept> {
private static final long serialVersionUID=2386841732225838685L;
public static final Comparator<AtomicConcept> INSTANCE=new AtomicConceptComparator();
public int compare(AtomicConcept o1,AtomicConcept o2) {
return o1.getIRI().compareTo(o2.getIRI());
}
protected Object readResolve() {
return INSTANCE;
}
}
public static class AtomicRoleComparator implements Serializable,Comparator<AtomicRole> {
private static final long serialVersionUID=3483541702854959793L;
public static final Comparator<AtomicRole> INSTANCE=new AtomicRoleComparator();
public int compare(AtomicRole o1,AtomicRole o2) {
return o1.getIRI().compareTo(o2.getIRI());
}
protected Object readResolve() {
return INSTANCE;
}
}
public static class IndividualComparator implements Serializable,Comparator<Individual> {
private static final long serialVersionUID=2386841732225838685L;
public static final Comparator<Individual> INSTANCE=new IndividualComparator();
public int compare(Individual o1,Individual o2) {
return o1.getIRI().compareTo(o2.getIRI());
}
protected Object readResolve() {
return INSTANCE;
}
}
}