package org.weso.wesearch.model;
import java.util.LinkedList;
import java.util.List;
import org.apache.log4j.Logger;
import org.weso.utils.OntoModelException;
import org.weso.wesearch.domain.Matter;
import org.weso.wesearch.domain.Matters;
import org.weso.wesearch.domain.Properties;
import org.weso.wesearch.domain.Property;
import org.weso.wesearch.domain.ValueSelector;
import org.weso.wesearch.domain.impl.JenaPropertyImpl;
import org.weso.wesearch.domain.impl.MatterImpl;
import org.weso.wesearch.domain.impl.PropertiesImpl;
import org.weso.wesearch.domain.impl.SubjectsImpl;
import com.hp.hpl.jena.ontology.OntClass;
import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.ontology.OntProperty;
import com.hp.hpl.jena.ontology.OntResource;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.rdf.model.Statement;
import com.hp.hpl.jena.util.iterator.ExtendedIterator;
import com.hp.hpl.jena.vocabulary.RDFS;
/**
* This is an auxiliary class that allow wesearch work with ontologies using
* Apache Jena.
* @author Ignacio Fuertes Bernardo
*
*/
public class OntologyHelper {
private static Logger logger = Logger.getLogger(OntologyHelper.class);
/**
* This method creates a matter from a uri and a jena model
* @param resource The uri of the resource
* @param model The model where is the resource
* @return The created matter
*/
public static Matter createMatter(String resource, OntModel model) {
String label = getLabel(resource, model);
String comment = getComment(resource, model);
return new MatterImpl(label, resource, comment);
}
/**
* This method creates a matter from a jena resource
* @param res The resource to create the matter
* @return The created matter
*/
public static Matter createMatter(Resource res) {
String uri = res.getURI();
String label = getLabel(res);
String comment = getComment(res);
return new MatterImpl(label, uri, comment);
}
/**
* This method obtains the property rdfs:label from a Jena resource
* @param res The resource to obtain the property rdfs:label
* @return The value of property rdfs:label
*/
public static String getLabel(Resource res) {
if(res instanceof OntResource) {
return getLabelFromOntResource(res);
} else {
return getLabelFromResource(res);
}
}
/**
* This method obtains the property rdfs:label from a Jena resource
* @param res The resource to obtain the property rdfs:label
* @return The value of property rdfs:label
*/
private static String getLabelFromResource(Resource res) {
Statement labelProp = res.getProperty(RDFS.label);
if (labelProp != null && labelProp.getString().length() > 0) {
return labelProp.getString();
} else {
return (res.getURI()!=null?res.getModel().getGraph()
.getPrefixMapping().shortForm(res.getURI()):
"Label not available");
}
}
/**
* This method obtains the property rdfs:label from a jena OntResource
* using xml:lang attribute.
* @param res The resource to obtain the property rdfs:label
* @return The value of the property rdfs:label
*/
private static String getLabelFromOntResource(Resource res) {
OntResource resource = ((OntResource)res);
if(resource.getLabel("es") != null) {
return resource.getLabel("es");
} else if (resource.getLabel("en") != null) {
return resource.getLabel("en");
} else if (resource.getLabel(null) != null) {
return resource.getLabel(null);
} else {
return (res.getURI()!=null?res.getModel().getGraph()
.getPrefixMapping().shortForm(res.getURI()):
"Label not available");
}
}
/**
* This method obtains the property rdfs:comment from a Jena resource
* @param res The resource to obtain the property rdfs:comment
* @return The value of property rdfs:comment
*/
public static String getComment(Resource res) {
if(res instanceof OntResource) {
return getCommentFromOntResource(res);
} else {
return getCommentFromResource(res);
}
}
/**
* This method obtains the property rdfs:comment from a Jena resource
* @param res The resource to obtain the property rdfs:comment
* @return The value of property rdfs:comment
*/
private static String getCommentFromResource(Resource res) {
Statement labelProp = res.getProperty(RDFS.comment);
if (labelProp != null && labelProp.getString().length() > 0) {
return labelProp.getString();
} else {
return (res.getURI()!=null?res.getModel().getGraph()
.getPrefixMapping().shortForm(res.getURI()):
"Comment not available");
}
}
/**
* This method obtains the property rdfs:comment from a jena OntResource
* using xml:lang attribute.
* @param res The resource to obtain the property rdfs:comment
* @return The value of the property rdfs:comment
*/
private static String getCommentFromOntResource(Resource res) {
OntResource ontResource = (OntResource)res;
if(ontResource.getComment("es") != null) {
return ontResource.getComment("es");
} else if (ontResource.getComment("en") != null) {
return ontResource.getComment("en");
} else if (ontResource.getComment(null) != null) {
return ontResource.getComment(null);
} else {
return (res.getURI()!=null?res.getModel().getGraph()
.getPrefixMapping().shortForm(res.getURI()):
"Comment not available");
}
}
/**
* This method obtains the property rdfs:label from the URI of a Jena
* resource
* @param resource The URI of the resource to obtain the property rdfs:label
* @param model The ontology model to obtain the property value
* @return The value of property rdfs:label
*/
public static String getLabel(String resource, OntModel model) {
OntClass res = model.getOntClass(resource);
if(res == null) {
return "Label not available";
}
return getLabel(res);
}
/**
* This method obtains the property rdfs:comment from the URI of a Jena
* resource
* @param resource The URI of the resource to obtain the property
* rdfs:comment
* @param model The ontology model to obtain the value
* @return The value of property rdfs:comment
*/
public static String getComment(String resource, OntModel model) {
OntClass res = model.getOntClass(resource);
if(res == null) {
return "Comment not available";
}
return getComment(res);
}
/**
* This method obtains all properties of one class of the ontologies
* @param ontClass The class to obtain all its properties
* @param superClasses A list of super-classes of the class to obtain all
* inherited properties
* @return A collection of all properties of one class
*/
public static Properties obtainPropertiesByMatter(OntClass ontClass,
ExtendedIterator<OntClass> superClasses) {
Properties properties = new PropertiesImpl();
extractPropertiesFromOntClass(properties, ontClass);
while(superClasses.hasNext()) {
OntClass auxOntClass = superClasses.next();
extractPropertiesFromOntClass(properties, auxOntClass);
}
return properties;
}
/**
* This method has to extract all properties of one class and insert them
* in a collection
* @param properties The collection in which the method has to insert the
* properties
* @param ontClass The class to extract all its properties
*/
public static void extractPropertiesFromOntClass(Properties properties,
OntClass ontClass) {
ExtendedIterator<OntProperty> ontProperties =
ontClass.listDeclaredProperties();
while(ontProperties.hasNext()) {
OntProperty ontProp = ontProperties.next();
properties.addProperty(createProperty(ontProp));
}
}
/**
* This method has to create a property object from a Jena resource
* @param res The resource from which the method has to create the property
* object
* @return The created Property
*/
public static Property createProperty(Resource res) {
String uri = res.getURI();
String label = getLabel(res);
String description = getComment(res);
return new JenaPropertyImpl(uri, label, description);
}
/**
* Given an OntProperty object, the method has to obtains its range.
* @param ontProperty The given property to obtain its range
* @return A String indicating the range of the property
*/
@SuppressWarnings("rawtypes")
public static String extractPropertyRange(OntProperty ontProperty) {
if(ontProperty != null) {
ExtendedIterator ranges = null;
if(ontProperty.isDatatypeProperty()) {
ranges = ontProperty.asDatatypeProperty().listRange();
return extractValueSelectorFromList(ranges);
} else {
return ValueSelector.OBJECT;
}
}
return ValueSelector.UNDEFINED;
}
/**
* This method has to extract the value selector according to a list of
* ontology resources.
* @param it The list of ontology resources
* @return The string corresponding to the value selector of the list of
* ontolgy resources
*/
@SuppressWarnings("rawtypes")
private static String extractValueSelectorFromList(
ExtendedIterator it) {
String result = null;
while(it.hasNext()) {
OntResource ont = (OntResource)it.next();
result = extractValueSelector(ont);
if(!result.equals(ValueSelector.UNDEFINED)) {
return result;
}
}
return ValueSelector.UNDEFINED;
}
/**
* This method extract the value selector of one ontolgy resource
* @param range The ontology resource to obtain its value selector
* @return A string indicates the value selector
*/
private static String extractValueSelector(OntResource range) {
if(range == null) {
return ValueSelector.UNDEFINED;
}
String uriRange = range.getURI();
if(isDateRange(uriRange)) {
return ValueSelector.DATE;
} else if (isNumericRange(uriRange)) {
return ValueSelector.NUMERIC;
} else if (isTextRange(uriRange)) {
return ValueSelector.TEXT;
}
return ValueSelector.UNDEFINED;
}
/**
* This method has to return if the range of a property is a text or no
* @param uriRange The range of a property
* @return A boolean indicates if the range must be a string or no
*/
private static boolean isTextRange(String uriRange) {
return uriRange.equals("http://www.w3.org/2001/XMLSchema#string") ||
uriRange.equals(
"http://www.w3.org/2000/01/rdf-schema#Literal");
}
/**
* This method has to return if the range of a property is numeric or no
* @param uriRange The range of a property
* @return A boolean indicates if the range must be a number or no
*/
private static boolean isNumericRange(String uriRange) {
return uriRange.equals("http://www.w3.org/2001/XMLSchema#decimal")
|| uriRange.equals("http://www.w3.org/2001/XMLSchema#float") ||
uriRange.equals("http://www.w3.org/2001/XMLSchema#double") ||
uriRange.equals("http://www.w3.org/2001/XMLSchema#long") ||
uriRange.equals("http://www.w3.org/2001/XMLSchema#integer") ||
uriRange.equals("http://www.w3.org/2001/XMLSchema#int");
}
/**
* This method has to return if the range is of date type
* @param uriRange The range of a property
* @return A boolean indicates if the range must be a date or no
*/
private static boolean isDateRange(String uriRange) {
return uriRange.equals("http://www.w3.org/2001/XMLSchema#date") ||
uriRange.equals("http://www.w3.org/2001/XMLSchema#dateTime") ||
uriRange.equals("http://www.w3.org/2001/XMLSchema#time");
}
/**
* This method has to create a collection of Matter objects that represents
* the range of a resource when its range is a class of the ontology
* @param listRange A list of classes of the ontology that can be range of
* a property
* @return A colleciont of Matter objects
* @throws OntoModelException This exception is thrown if there are some
* problem with the ontology
*/
public static Matters createRangeMatters(
ExtendedIterator<? extends OntResource> listRange)
throws OntoModelException {
if(listRange == null) {
logger.error("The list of ranges cannot be null");
throw new OntoModelException("The list of ranges cannot be null");
}
Matters matters = new SubjectsImpl();
while(listRange.hasNext()) {
OntResource res = listRange.next();
if(res.getURI() != null) {
Matter m = new MatterImpl(getLabel(res), res.getURI(),
getComment(res));
matters.addMatter(m);
}
}
return matters;
}
/**
* This method has to extracts all subclasses of one class of the ontology
* @param matter The class of the ontolgy that the method has to extract
* its subclasses
* @param model The ontology model from which the method has to obtain
* the subclasses
* @return A list of URIs of the subclasses
*/
public static List<String> extractSubclasses(Matter matter,
OntModel model) {
List<String> result = new LinkedList<String>();
OntClass ontClass = model.getOntClass(matter.getUri());
if(ontClass != null) {
ExtendedIterator<OntClass> it = ontClass.listSubClasses();
while(it.hasNext()) {
OntClass aux = it.next();
result.add(aux.getURI());
}
}
return result;
}
}