/*
* (c) Copyright 2010-2011 AgileBirds
*
* This file is part of OpenFlexo.
*
* OpenFlexo is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* OpenFlexo 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenFlexo. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.openflexo.foundation.ontology.owl;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.openflexo.foundation.Inspectors;
import org.openflexo.foundation.ontology.OntologyClass;
import org.openflexo.foundation.ontology.OntologyObject;
import org.openflexo.foundation.ontology.OntologyProperty;
import org.openflexo.toolbox.StringUtils;
import com.hp.hpl.jena.ontology.Individual;
import com.hp.hpl.jena.ontology.OntClass;
import com.hp.hpl.jena.rdf.model.Resource;
public class OWLClass extends OWLObject<OntClass> implements OntologyClass, Comparable<OntologyClass> {
private static final Logger logger = Logger.getLogger(OntologyClass.class.getPackage().getName());
private OntClass ontClass;
private final Vector<OWLClass> superClasses;
protected OWLClass(OntClass anOntClass, OWLOntology ontology) {
super(anOntClass, ontology);
superClasses = new Vector<OWLClass>();
ontClass = anOntClass;
}
/**
* Init this OntologyClass, given base OntClass
*/
protected void init() {
updateOntologyStatements(ontClass);
updateSuperClasses(ontClass);
}
@Override
public void delete() {
getFlexoOntology().removeClass(this);
getOntResource().remove();
getFlexoOntology().updateConceptsAndProperties();
super.delete();
deleteObservers();
}
/**
* Update this OntologyClass, given base OntClass
*/
@Override
protected void update() {
update(ontClass);
}
/**
* Update this OntologyClass, given base OntClass which is assumed to extends base OntClass
*
* @param anOntClass
*/
protected void update(OntClass anOntClass) {
updateOntologyStatements(anOntClass);
updateSuperClasses(anOntClass);
ontClass = anOntClass;
}
@Override
public void setName(String aName) {
renameURI(aName, ontClass, OntClass.class);
}
@Override
protected void _setOntResource(OntClass r) {
ontClass = r;
}
@Override
public OWLClass getOriginalDefinition() {
return (OWLClass) super.getOriginalDefinition();
}
private void appendToSuperClasses(OWLClass superClass) {
if (getURI().equals(OWL2URIDefinitions.OWL_THING_URI)) {
return;
}
if (superClass == this) {
return;
}
if (superClass.redefinesOriginalDefinition()) {
if (superClasses.contains(superClass.getOriginalDefinition())) {
superClasses.remove(superClass.getOriginalDefinition());
}
}
if (!superClasses.contains(superClass)) {
superClasses.add(superClass);
if (logger.isLoggable(Level.FINE)) {
logger.fine("Add " + superClass.getName() + " as a super class of " + getName());
}
}
}
private void updateSuperClasses(OntClass anOntClass) {
superClasses.clear();
if (redefinesOriginalDefinition()) {
for (OWLClass c : getOriginalDefinition().getSuperClasses()) {
if (!c.isThing()) {
appendToSuperClasses(c);
}
}
// superClasses.addAll(getOriginalDefinition().getSuperClasses());
}
// logger.info("updateSuperClasses for " + getURI());
Iterator it = anOntClass.listSuperClasses(true);
while (it.hasNext()) {
OntClass father = (OntClass) it.next();
OWLClass fatherClass = getOntology().retrieveOntologyClass(father);// getOntologyLibrary().getClass(father.getURI());
if (fatherClass != null) {
appendToSuperClasses(fatherClass);
}
}
// If this class is equivalent to the intersection of some other classes, then all those operand classes are super classes of this
// class
if (getEquivalentClass() instanceof OWLIntersectionClass) {
for (OWLClass operand : ((OWLIntersectionClass) getEquivalentClass()).getOperands()) {
appendToSuperClasses(operand);
}
}
// If computed ontology is either not RDF, nor RDFS, nor OWL
// add OWL Thing as parent
if (getFlexoOntology() != getOntologyLibrary().getRDFOntology() && getFlexoOntology() != getOntologyLibrary().getRDFSOntology()) {
if (isNamedClass() && !isThing()) {
OWLClass THING_CLASS = getOntology().getRootClass();
appendToSuperClasses(THING_CLASS);
}
}
}
@Deprecated
@Override
public String getClassNameKey() {
return "ontology_class";
}
@Override
public String getFullyQualifiedName() {
return "OntologyClass:" + getURI();
}
public static final Comparator<OntologyClass> COMPARATOR = new Comparator<OntologyClass>() {
@Override
public int compare(OntologyClass o1, OntologyClass o2) {
return Collator.getInstance().compare(o1.getName(), o2.getName());
}
};
@Override
public String getInspectorName() {
if (getIsReadOnly()) {
return Inspectors.VE.ONTOLOGY_CLASS_READ_ONLY_INSPECTOR; // read-only
} else {
return Inspectors.VE.ONTOLOGY_CLASS_INSPECTOR;
}
}
@Override
public int compareTo(OntologyClass o) {
return COMPARATOR.compare(this, o);
}
@Override
public OntClass getOntResource() {
return ontClass;
}
private static boolean isSuperClassOf(OntClass parentClass, OntClass subClass) {
if (parentClass == null) {
return false;
}
if (subClass == null) {
return false;
}
if (parentClass.equals(subClass)) {
return true;
}
Iterator<OntClass> it = subClass.listSuperClasses();
while (it.hasNext()) {
OntClass p = it.next();
if (p.equals(parentClass)) {
return true;
}
if (isSuperClassOf(parentClass, p)) {
return true;
}
}
return false;
}
private static boolean isSuperClassOf(OntClass parentClass, Individual individual) {
if (parentClass == null) {
return false;
}
if (individual == null) {
return false;
}
Iterator<Resource> it = individual.listRDFTypes(false);
while (it.hasNext()) {
Resource r = it.next();
if (r.canAs(OntClass.class)) {
OntClass c = r.as(OntClass.class);
if (c.equals(parentClass)) {
return true;
}
if (isSuperClassOf(parentClass, c)) {
return true;
}
}
}
return false;
}
@Override
public boolean isSuperConceptOf(OntologyObject concept) {
if (OWL2URIDefinitions.OWL_THING_URI.equals(getURI())) {
return true;
}
if (concept instanceof OWLIndividual) {
OWLIndividual ontologyIndividual = (OWLIndividual) concept;
// Doesn't work, i dont know why
// return ontologyIndividual.getIndividual().hasOntClass(ontClass);
return isSuperClassOf(ontClass, ontologyIndividual.getIndividual());
}
if (concept instanceof OWLClass) {
OWLClass ontologyClass = (OWLClass) concept;
// Doesn't work, i dont know why
// return ontologyClass.getOntResource().hasSuperClass(ontClass);
// return isSuperClassOf(ontClass, ontologyClass.getOntResource());
return isSuperClassOf(ontologyClass);
}
return false;
}
@Override
public boolean isSuperClassOf(OntologyClass aClass) {
if (aClass == this) {
return true;
}
if (equalsToConcept(aClass)) {
return true;
}
if (OWL2URIDefinitions.OWL_THING_URI.equals(getURI())) {
return true;
}
if (aClass instanceof OWLClass) {
for (OWLClass c : ((OWLClass) aClass).getSuperClasses()) {
if (isSuperClassOf(c)) {
return true;
}
}
}
return false;
}
/**
* Return all direct super classes of this class
*
* @return
*/
@Override
public Vector<OWLClass> getSuperClasses() {
return superClasses;
}
/**
* Return all direct and infered super classes of this class
*
* @return
*/
@Override
public Set<OWLClass> getAllSuperClasses() {
Set<OWLClass> returned = new HashSet<OWLClass>();
for (OWLClass c : getSuperClasses()) {
returned.add(c);
returned.addAll(c.getAllSuperClasses());
}
return returned;
}
/**
* Add super class to this class
*
* @param aClass
*/
@Override
public SubClassStatement addSuperClass(OntologyClass father) {
if (father instanceof OWLClass) {
getOntResource().addSuperClass(((OWLClass) father).getOntResource());
updateOntologyStatements();
return getSubClassStatement(father);
}
logger.warning("Class " + father + " is not a OWLClass");
return null;
}
/**
* Return a vector of Ontology class, as a subset of getSubClasses(), which correspond to all classes necessary to see all classes
* belonging to supplied context, which is an ontology
*
* @param context
* @return
*/
@Deprecated
public Vector<OntologyClass> getSubClasses(OWLOntology context) {
/*Vector<OWLClass> returned = new Vector<OWLClass>();
for (OWLClass aClass : getSubClasses()) {
if (isRequired(aClass, context)) {
returned.add(aClass);
}
}
return returned;*/
return null;
}
/*private boolean isRequired(OntologyClass aClass, FlexoOntology context) {
if (aClass.getFlexoOntology() == context) {
return true;
}
for (OntologyClass aSubClass : aClass.getSubClasses()) {
if (isRequired(aSubClass, context)) {
return true;
}
}
for (OntologyIndividual anIndividual : aClass.getIndividuals()) {
if (anIndividual.getFlexoOntology() == context) {
return true;
}
}
return false;
}*/
@Override
public String getDisplayableDescription() {
/*String extendsLabel = " extends ";
boolean isFirst = true;
for (OntologyClass s : superClasses) {
extendsLabel += (isFirst ? "" : ",") + s.getName();
isFirst = false;
}
return "Class " + getName() + extendsLabel;*/
return getName();
}
@Override
public boolean isOntologyClass() {
return true;
}
@Override
protected void recursivelySearchRangeAndDomains() {
super.recursivelySearchRangeAndDomains();
for (OWLClass aClass : getSuperClasses()) {
propertiesTakingMySelfAsRange.addAll(aClass.getPropertiesTakingMySelfAsRange());
propertiesTakingMySelfAsDomain.addAll(aClass.getPropertiesTakingMySelfAsDomain());
}
OWLClass CLASS_CONCEPT = getOntology().getClass(OWL_CLASS_URI);
// CLASS_CONCEPT is generally non null but can be null when reading RDFS for exampel
if (CLASS_CONCEPT != null) {
propertiesTakingMySelfAsRange.addAll(CLASS_CONCEPT.getPropertiesTakingMySelfAsRange());
propertiesTakingMySelfAsDomain.addAll(CLASS_CONCEPT.getPropertiesTakingMySelfAsDomain());
}
/*Vector<OntologyClass> alreadyComputed = new Vector<OntologyClass>();
if (redefinesOriginalDefinition()) {
_appendRangeAndDomains(getOriginalDefinition(), alreadyComputed);
}
for (OntologyClass aClass : getSuperClasses()) {
_appendRangeAndDomains(aClass, alreadyComputed);
}*/
}
/*private void _appendRangeAndDomains(OntologyClass superClass, Vector<OntologyClass> alreadyComputed) {
if (alreadyComputed.contains(superClass)) {
return;
}
alreadyComputed.add(superClass);
for (OntologyProperty p : superClass.getDeclaredPropertiesTakingMySelfAsDomain()) {
if (!propertiesTakingMySelfAsDomain.contains(p)) {
propertiesTakingMySelfAsDomain.add(p);
}
}
for (OntologyProperty p : superClass.getDeclaredPropertiesTakingMySelfAsRange()) {
if (!propertiesTakingMySelfAsRange.contains(p)) {
propertiesTakingMySelfAsRange.add(p);
}
}
for (OntologyClass superSuperClass : superClass.getSuperClasses()) {
_appendRangeAndDomains(superSuperClass, alreadyComputed);
}
}*/
private OntologyClass equivalentClass;
private List<OntologyClass> equivalentClasses = new ArrayList<OntologyClass>();
@Override
public void updateOntologyStatements(OntClass anOntResource) {
super.updateOntologyStatements(anOntResource);
equivalentClasses.clear();
for (OWLStatement s : getSemanticStatements()) {
if (s instanceof EquivalentClassStatement) {
if (((EquivalentClassStatement) s).getEquivalentObject() instanceof OntologyClass) {
equivalentClass = (OntologyClass) ((EquivalentClassStatement) s).getEquivalentObject();
equivalentClasses.add(equivalentClass);
}
}
}
}
/**
* Return equivalent class, asserting there is only one equivalent class statement
*
* @return
*/
public OntologyClass getEquivalentClass() {
return equivalentClass;
}
/**
* Return all restrictions related to supplied property
*
* @param property
* @return
*/
public List<OntologyRestrictionClass> getRestrictions(OntologyProperty property) {
List<OntologyRestrictionClass> returned = new ArrayList<OntologyRestrictionClass>();
for (OntologyClass c : getSuperClasses()) {
if (c instanceof OntologyRestrictionClass) {
OntologyRestrictionClass r = (OntologyRestrictionClass) c;
if (r.getProperty() == property) {
returned.add(r);
}
}
}
return returned;
}
@Override
public String getHTMLDescription() {
StringBuffer sb = new StringBuffer();
sb.append("<html>");
sb.append("Class <b>" + getName() + "</b><br>");
sb.append("<i>" + getURI() + "</i><br>");
sb.append("<b>Asserted in:</b> " + getOntology().getURI() + "<br>");
if (redefinesOriginalDefinition()) {
sb.append("<b>Redefines:</b> " + getOriginalDefinition() + "<br>");
}
sb.append("<b>Superclasses:</b>");
for (OWLClass c : getSuperClasses()) {
sb.append(" " + c.getDisplayableDescription());
}
sb.append("</html>");
return sb.toString();
}
/**
* Indicates if this class represents a named class
*/
@Override
public boolean isNamedClass() {
return StringUtils.isNotEmpty(getURI());
}
/**
* Indicates if this class represents the Thing root concept
*/
@Override
public boolean isThing() {
return isNamedClass() && getURI().equals(OWL2URIDefinitions.OWL_THING_URI);
}
}