Updates for enabling the association of sparql queries with OWL classes and allowing the individual response builder to retrieve data (using data getters) and make that data available to the templates. Additionally, I'm adding a new data post processor that allows 'duplicate' results (or results with the same object uri for the main subject uri) to be returned - this relates to work being done by Frances for Vitro. This post processor will need to be explicitly included for it to be used.

This commit is contained in:
hjkhjk54 2012-09-24 16:14:51 +00:00
parent 4f7e6d0ee4
commit 0b3d14ebab
5 changed files with 213 additions and 2 deletions

View file

@ -31,6 +31,7 @@ import edu.cornell.mannlib.vitro.webapp.dao.jena.QueryUtils;
import edu.cornell.mannlib.vitro.webapp.dao.ObjectPropertyDao;
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
import edu.cornell.mannlib.vitro.webapp.utils.dataGetter.ExecuteDataRetrieval;
import edu.cornell.mannlib.vitro.webapp.web.beanswrappers.ReadOnlyBeansWrapper;
import edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual.IndividualTemplateModel;
import edu.cornell.mannlib.vitro.webapp.web.templatemodels.individuallist.ListedIndividual;
@ -59,6 +60,7 @@ class IndividualResponseBuilder {
private final WebappDaoFactory wadf;
private final IndividualDao iDao;
private final ObjectPropertyDao opDao;
private final ExecuteDataRetrieval eDataRetrieval;
private final Individual individual;
@ -69,6 +71,8 @@ class IndividualResponseBuilder {
this.opDao = wadf.getObjectPropertyDao();
this.individual = individual;
//initializing execute data retrieval
this.eDataRetrieval = new ExecuteDataRetrieval(this.vreq, this.vreq.getDisplayModel(), this.individual);
}
ResponseValues assembleResponse() throws TemplateModelException {
@ -80,6 +84,14 @@ class IndividualResponseBuilder {
body.put("temporalVisualizationEnabled", getTemporalVisualizationFlag());
body.put("verbosePropertySwitch", getVerbosePropertyValues());
//Execute data getters that might apply to this individual, e.g. because of the class of the individual
try{
this.eDataRetrieval.executeDataGetters(body);
} catch(Exception ex) {
log.error("Data retrieval for individual lead to error", ex);
}
//Individual template model
IndividualTemplateModel itm = getIndividualTemplateModel(individual);
/* We need to expose non-getters in displaying the individual's property list,
* since it requires calls to methods with parameters.

View file

@ -73,6 +73,25 @@ public class DataGetterUtils {
log.debug("getDataGettersForPage: " + dgList);
return dgList;
}
/**
* Get a list of DataGetter objects that are associated with a JAVA class.
* This allows the individual profile for an individual of a specific class to be returned .
*/
public static List<DataGetter> getDataGettersForClass( VitroRequest vreq, Model displayModel, String classURI)
throws InstantiationException, IllegalAccessException, ClassNotFoundException, IllegalArgumentException, SecurityException, InvocationTargetException, NoSuchMethodException{
//get data getter uris for pageURI
List<String> dgUris = getDataGetterURIsForClassURI( displayModel, classURI);
List<DataGetter> dgList = new ArrayList<DataGetter>();
for( String dgURI: dgUris){
DataGetter dg =dataGetterForURI(vreq, displayModel, dgURI) ;
if( dg != null )
dgList.add(dg);
}
log.debug("getDataGettersForClass: " + dgList);
return dgList;
}
/**
* Returns a DataGetter using information in the
@ -163,7 +182,7 @@ public class DataGetterUtils {
private static List<String> getDataGetterURIsForPageURI(Model displayModel, String pageURI) {
String query = prefixes +
"SELECT ?dataGetter WHERE { ?pageURI display:hasDataGetter ?dataGetter }";
"SELECT ?dataGetter WHERE { ?pageURI display:hasDataGetter ?dataGetter. }";
Query dgForPageQuery = QueryFactory.create(query);
QuerySolutionMap initialBindings = new QuerySolutionMap();
@ -188,6 +207,35 @@ public class DataGetterUtils {
return dgURIs;
}
//Get data getters for a specific JAVA class - associates data getters with individuals for a specific JAVA class
private static List<String> getDataGetterURIsForClassURI(Model displayModel, String classURI) {
//Class URI will be substituted in so this is for a specific class uri
String query = prefixes +
"SELECT ?dataGetter WHERE { ?classURI display:hasDataGetter ?dataGetter }";
Query dgForPageQuery = QueryFactory.create(query);
QuerySolutionMap initialBindings = new QuerySolutionMap();
initialBindings.add("classURI", ResourceFactory.createResource( classURI ));
List<String> dgURIs = new ArrayList<String>();
displayModel.enterCriticalSection(false);
try{
QueryExecution qexec = QueryExecutionFactory.create(dgForPageQuery,displayModel,initialBindings );
try{
ResultSet results = qexec.execSelect();
while (results.hasNext()) {
QuerySolution soln = results.nextSolution();
Resource dg = soln.getResource("dataGetter");
if( dg != null && dg.getURI() != null){
dgURIs.add( dg.getURI());
}
}
}finally{ qexec.close(); }
}finally{ displayModel.leaveCriticalSection(); }
return dgURIs;
}
private static String chooseType(List<String> types, Model displayModel, String dataGetterURI) throws IllegalAccessException {
//currently just get the first one that is not owl:Thing
for(String type : types){

View file

@ -0,0 +1,110 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.utils.dataGetter;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletContext;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.json.JSONArray;
import org.json.JSONObject;
import com.hp.hpl.jena.query.Query;
import com.hp.hpl.jena.query.QueryExecution;
import com.hp.hpl.jena.query.QueryExecutionFactory;
import com.hp.hpl.jena.query.QueryFactory;
import com.hp.hpl.jena.query.QuerySolution;
import com.hp.hpl.jena.query.QuerySolutionMap;
import com.hp.hpl.jena.query.ResultSet;
import com.hp.hpl.jena.rdf.model.Literal;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.RDFNode;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.rdf.model.ResourceFactory;
import com.hp.hpl.jena.shared.Lock;
import com.hp.hpl.jena.vocabulary.OWL;
import edu.cornell.mannlib.vitro.webapp.beans.DataProperty;
import edu.cornell.mannlib.vitro.webapp.beans.Individual;
import edu.cornell.mannlib.vitro.webapp.beans.VClass;
import edu.cornell.mannlib.vitro.webapp.beans.VClassGroup;
import edu.cornell.mannlib.vitro.webapp.controller.Controllers;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.IndividualListController;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.IndividualListController.PageRecord;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder;
import edu.cornell.mannlib.vitro.webapp.controller.json.JsonServlet;
import edu.cornell.mannlib.vitro.webapp.dao.DisplayVocabulary;
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
import edu.cornell.mannlib.vitro.webapp.dao.jena.VClassGroupCache;
public class ExecuteDataRetrieval {
final static Log log = LogFactory.getLog(ExecuteDataRetrieval.class);
Individual individual = null;
VitroRequest vreq = null;
Model displayModel = null;
/**
* Constructor with display model and data getter URI that will be called by reflection.
*/
public ExecuteDataRetrieval(VitroRequest vreq, Model displayModel, Individual individual){
//not sure if we need display model or vreq for this?
this.individual = individual;
this.vreq = vreq;
this.displayModel = displayModel;
}
public List<DataGetter> retrieveDataGetters() {
//Using a hashset to prevent duplicates
//Would this work with interfaces? In this case, all of them would be interfaces?
HashSet<DataGetter> dataGetters = new HashSet<DataGetter>();
List<VClass> vclasses = this.individual.getVClasses();
//For any of the vclasses that apply to this individual, check whether
//there are any datagetter assigned for that class
try {
for(VClass v: vclasses) {
String classURI = v.getURI();
//How to handle duplicates?
dataGetters.addAll(DataGetterUtils.getDataGettersForClass(vreq, displayModel, classURI));
}
}
catch(Exception ex) {
log.error("Error occurred in retrieving datagetters for vclasses", ex);
}
List<DataGetter> dgList = new ArrayList<DataGetter>(dataGetters);
return dgList;
}
//retrieve data getters for the classes that apply to this individual
//execute the data getters, and return the data in a map
public void executeDataGetters(Map<String, Object> mapForTemplate)
throws Exception {
List<DataGetter> dgList = retrieveDataGetters();
//Put in individual URI in map for template - e.g. sparql query can then use that information and add bindings
mapForTemplate.put("individualURI", this.individual.getURI());
for( DataGetter dg : dgList){
Map<String,Object> moreData = dg.getData(mapForTemplate);
if( moreData != null ){
mapForTemplate.putAll(moreData);
}
}
}
}

View file

@ -0,0 +1,42 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual;
import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
/** The object property data postprocessor that is used if the view does not specify another postprocessor */
public class MaintainDuplicatesObjectPropertyDataPostProcessor extends BaseObjectPropertyDataPostProcessor {
private static final Log log = LogFactory.getLog(DefaultObjectPropertyDataPostProcessor.class);
public MaintainDuplicatesObjectPropertyDataPostProcessor(ObjectPropertyTemplateModel optm,
WebappDaoFactory wdf) {
super(optm, wdf);
}
@Override
protected void process(Map<String, String> map) {
// no default data postprocessing defined yet
}
@Override
public void process(List<Map<String, String>> data) {
if (data.isEmpty()) {
log.debug("No data to postprocess for property " + objectPropertyTemplateModel.getUri());
return;
}
//Process list is not called as it removes duplicates
for (Map<String, String> map : data) {
process(map);
}
}
}

View file

@ -53,7 +53,6 @@ owl:ObjectProperty
<java:edu.cornell.mannlib.vitro.webapp.utils.dataGetter.SparqlQueryDataGetter>
a owl:Class .
########Data Properties#########
###Basic