package org.weso.wesearch; import java.io.IOException; import java.util.Iterator; import java.util.List; import org.apache.log4j.Logger; import org.weso.utils.IndexerCreator; import org.weso.utils.OntoModelException; import org.weso.utils.QueryBuilderException; import org.weso.utils.WesearchException; import org.weso.wesearch.context.Context; 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.Query; import org.weso.wesearch.domain.SPARQLQueryBuilder; import org.weso.wesearch.domain.ValueSelector; import org.weso.wesearch.domain.impl.PropertiesImpl; import org.weso.wesearch.domain.impl.SPARQLQuery; import org.weso.wesearch.domain.impl.SubjectsImpl; import org.weso.wesearch.domain.impl.ValueSelectorImpl; import org.weso.wesearch.domain.impl.filters.SPARQLFilters; import org.weso.wesearch.domain.impl.values.ObjectValue; import org.weso.wesearch.model.OntologyHelper; import weso.mediator.config.Configuration; import weso.mediator.core.business.SuggestionException; import weso.mediator.core.domain.Suggestion; import weso.mediator.core.domain.lucene.IndexLucene; import weso.mediator.facade.WESOMed; import weso.mediator.factory.FacadeFactory; 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.util.iterator.ExtendedIterator; /** * This class is an implementation of Wesearch based on Jena * @author Ignacio Fuertes Bernardo * */ public class JenaWesearch implements Wesearch { private static Logger logger = Logger.getLogger(JenaWesearch.class); /** * The object that save the context of the wesarch */ private Context ctx; /** * An instance of wesomed that allow text search over the ontologies */ private WESOMed<IndexLucene> wesomed; @SuppressWarnings("unchecked") public JenaWesearch(Context ctx) throws WesearchException { this.ctx = ctx; wesomed = (WESOMed<IndexLucene>) FacadeFactory.getFacade(); initializeWesomed(); } @Override public Matters getMatters(String stem) throws WesearchException { validateParams(stem); try { if(isValidStem(stem)) { return createMatterFromResources( ((OntModel)ctx.getOntologiesModel().getModel()) .listClasses()); } List<Suggestion> classes = wesomed.getSuggestions(stem, Configuration.getProperty("index_dir_classes")); return createMatterFromResourceId(classes.iterator()); } catch (SuggestionException e) { throw new WesearchException(e.getMessage()); } catch (OntoModelException e) { throw new WesearchException(e.getMessage()); } } /** * This method has to check if there is any object in the array that is null * @param params An array of objects that have to check * @throws WesearchException This exception is thrown if there is a null * object in the array */ private void validateParams(Object... params) throws WesearchException { for(int i = 0; i < params.length; i++) { if(params[i] == null) { logger.error("There is a param in the request null"); throw new WesearchException("There is a param in the request " + "null"); } } } /** * This method has to valid if the string is valid to obtain a suggestion * @param stem The string to valid * @return A boolean indicates if the string is valid */ private boolean isValidStem(String stem) { return stem.equals(""); } /** * This method has to create a collection of subjects from an iterator of * OntClass objects * @param it The iterator that contains the source objects to convert * @return A collection of subjects */ private Matters createMatterFromResources(ExtendedIterator<OntClass> it) { Matters matters = new SubjectsImpl(); while(it.hasNext()) { OntClass clazz = it.next(); if(clazz.getURI() != null) { matters.addMatter(OntologyHelper.createMatter(clazz)); } } return matters; } /** * This method has to create a collection of subjects from a list of * suggestions obtained by wesomed * @param it An iterator over the list of suggestions * @return A collection of subjects * @throws OntoModelException This exception is thrown if there are * some problem creating the subjects */ private Matters createMatterFromResourceId(Iterator<Suggestion> it) throws OntoModelException { Matters matters = new SubjectsImpl(); while(it.hasNext()) { Suggestion clazz = it.next(); String uriClass = clazz.getResourceId(); if(uriClass != null) { matters.addMatter(OntologyHelper.createMatter(uriClass, (OntModel)ctx.getOntologiesModel().getModel())); } } return matters; } @Override public Properties getProperties(Matter s, String stem) throws WesearchException { validateParams(s, stem); try { Properties allProperties = obtainAllPropertiesByMatter(s); if(isValidStem(stem)) { return allProperties; } List<Suggestion> filteredProperties = wesomed.getSuggestions(stem, Configuration.getProperty("index_dir_properties")); return matchingProperties(allProperties, filteredProperties); } catch (SuggestionException e) { throw new WesearchException(e.getMessage()); } catch (OntoModelException e) { throw new WesearchException(e.getMessage()); } } /** * This method has to find the properties that are in both lists * @param allProperties All properties of one class of the ontology * @param filteredProperties All properties that are result of text search * @return All properties that are in both lists */ private Properties matchingProperties(Properties allProperties, List<Suggestion> filteredProperties) { Properties result = new PropertiesImpl(); Iterator<Property> it = allProperties.iterator(); while(it.hasNext()) { Property p = it.next(); if(isPropertySought(filteredProperties, p)) { result.addProperty(p); } } return result; } /** * This method returns if one property is in a list of properties * @param filteredProperties List of properties which are looking for a * particular property * @param p Property that method has to find in the list * @return boolean that indicates if the property is in the list */ private boolean isPropertySought(List<Suggestion> filteredProperties, Property p) { for(Suggestion sug : filteredProperties) { if(sug.getResourceId().equals(p.getUri())) { return true; } } return false; } /** * This method has to obtain all properties of one determinate class from * the ontologies * @param matter A class of an ontology to obtain all it's properties * @return A collection of properties * @throws OntoModelException This exception is thrown if there are any * problem obtaining the properties */ private Properties obtainAllPropertiesByMatter(Matter matter) throws OntoModelException { Properties properties = new PropertiesImpl(); OntModel model = (OntModel)ctx.getOntologiesModel().getModel(); OntClass ontClass = model.getOntClass(matter.getUri()); properties = OntologyHelper.obtainPropertiesByMatter(ontClass, ontClass.listSuperClasses()); return properties; } @Override public ValueSelector getValueSelector(Matter s, Property p) throws WesearchException { validateParams(s, p); try { OntModel ontModel = (OntModel)ctx.getOntologiesModel().getModel(); OntProperty ontProperty = ontModel.getOntProperty(p.getUri()); String type = OntologyHelper.extractPropertyRange(ontProperty); if(type.equals(ValueSelector.OBJECT)) { ValueSelector selector = new ValueSelectorImpl(type); Matters matters = OntologyHelper.createRangeMatters( ontProperty.listRange()); selector.setValue(new ObjectValue(matters)); return selector; } return new ValueSelectorImpl(type); } catch (OntoModelException e) { throw new WesearchException(e.getMessage()); } } @Override public Query createQuery(Matter s, Property p, ValueSelector v) throws WesearchException { validateParams(v); try { Query query = new SPARQLQuery(); addTypeClauseToQuery("res", query.getNextVarName(), query, s); String object = query.getNextVarName(); query.addClause(SPARQLQueryBuilder.getPropertyClause("res", p, object)); addFilterToQuery(v, query, object); return query; }catch(IOException e) { logger.error("Cannot read sparql queries variables"); throw new WesearchException("Cannot read sparql queries variables"); }catch(QueryBuilderException e) { throw new WesearchException(e.getMessage()); } catch (OntoModelException e) { throw new WesearchException(e.getMessage()); } } /** * This method has to add a filter clause to the query that receives as a * parameter * @param v The value selector to filter in the query * @param query The query to adds the filter * @param object The name of the variable that has to filter in the query * @throws QueryBuilderException This exception is thrown if there is a * problem generating the filter clause */ private void addFilterToQuery(ValueSelector v, Query query, String object) throws QueryBuilderException { if(!v.getType().equals(ValueSelector.OBJECT)) { query.addFilter(object, SPARQLQueryBuilder.getFilter( object, v)); } else { query.addFilter(object, null); } } /** * This method adds a type filter to a given query. * @param s The type that must have the variable to filter * @param query Query to add the type filter * @param varName Name of the variable to filter * @throws OntoModelException This exception is thrown if there are some * problem during extraction of information over the ontology * @throws QueryBuilderException This exception is thrown if there are some * problem generating the query */ private void addTypeFilter(Matter s, Query query, String varName) throws OntoModelException, QueryBuilderException { SPARQLFilters filters = SPARQLQueryBuilder.getClassFilter(varName, s, ctx.getOntologiesModel()); query.addFilters(varName, filters); } /** * This method has to add a type clause to the query that receives as a * parameter * @param subject The name of the variable that has to be an instance * of a determinate class * @param object The name of the variable that has to be filtered * @param query The query to add the filter * @param matter The matter to filter * @throws OntoModelException This exception is thrown if there is a problem * generating the filter clause * @throws QueryBuilderException This exception is thrown if there is a * problem generating the filter clause */ private void addTypeClauseToQuery(String subject, String object, Query query, Matter matter) throws OntoModelException, QueryBuilderException { query.addClause(SPARQLQueryBuilder.getTypeClause(subject, object)); addTypeFilter(matter, query, object); } @Override public Query combineQuery(Query q, Matter s, Property p, ValueSelector v) throws WesearchException { validateParams(q, s, p, v); try { String subject = ""; String object = q.getNextVarName(); if(q.isPropertyForResult()) { subject = "res"; } else { //Add type clausules to query subject = q.obtainAuxiliarVarName(); addTypeClauseToQuery(subject, object, q, s); object = q.getNextVarName(); } //Add property clause to query q.addClause(SPARQLQueryBuilder.getPropertyClause(subject, p, object)); addFilterToQuery(v, q, object); } catch (QueryBuilderException e) { throw new WesearchException(e.getMessage()); } catch (OntoModelException e) { throw new WesearchException(e.getMessage()); } return q; } @Override public String version() { return "0.1"; } /** * This method has to initialized wesomed * @throws WesearchException This exception is thrown if there are * some problem reading the file that contains queries to extract * information to index */ private void initializeWesomed() throws WesearchException { try { indexClasses(); indexProperties(); } catch (IOException e) { logger.error("Cannot read files that contains queries: " + e.getMessage()); throw new WesearchException(e.getMessage()); } catch (SuggestionException e) { throw new WesearchException(e.getMessage()); } } /** * This method has to index all properties of the ontologies in wesomed * to allow text search over them. * @throws IOException This exception is thrown if there are some problems * reading the file that contains the query to extract properties. * @throws SuggestionException This exception is thrown if there are some * problems indexing properties in wesomed */ private void indexProperties() throws IOException, SuggestionException { List<IndexLucene> indexers = IndexerCreator.createIndexerForProperties(); String query = Configuration.getContentsFromProperty("query_properties"); wesomed.indexEntities( Configuration.getProperty("index_dir_properties"), query, indexers); } /** * This method has to index all classes of the ontologies in wesomed to * allow text search over them. * @throws IOException This exception is thrown if there are some problems * reading the file that contains the query to extract classes. * @throws SuggestionException This exception is throw if there are some * problems indexing classes in wesomed. */ private void indexClasses() throws IOException, SuggestionException { List<IndexLucene> indexers = IndexerCreator.createIndexerForClasses(); String query = Configuration.getContentsFromProperty("query_classes"); wesomed.indexEntities( Configuration.getProperty("index_dir_classes"), query, indexers); } }