diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/individual/IndividualResponseBuilder.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/individual/IndividualResponseBuilder.java index 7e5855582..a70b56ec2 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/individual/IndividualResponseBuilder.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/individual/IndividualResponseBuilder.java @@ -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. diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/DataGetterUtils.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/DataGetterUtils.java index 8edb7bd0f..73e582dfe 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/DataGetterUtils.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/DataGetterUtils.java @@ -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 getDataGettersForClass( VitroRequest vreq, Model displayModel, String classURI) + throws InstantiationException, IllegalAccessException, ClassNotFoundException, IllegalArgumentException, SecurityException, InvocationTargetException, NoSuchMethodException{ + //get data getter uris for pageURI + List dgUris = getDataGetterURIsForClassURI( displayModel, classURI); + + List dgList = new ArrayList(); + 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 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 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 dgURIs = new ArrayList(); + 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 types, Model displayModel, String dataGetterURI) throws IllegalAccessException { //currently just get the first one that is not owl:Thing for(String type : types){ diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/ExecuteDataRetrieval.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/ExecuteDataRetrieval.java new file mode 100644 index 000000000..64eb31c87 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/ExecuteDataRetrieval.java @@ -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 retrieveDataGetters() { + //Using a hashset to prevent duplicates + //Would this work with interfaces? In this case, all of them would be interfaces? + HashSet dataGetters = new HashSet(); + List 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 dgList = new ArrayList(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 mapForTemplate) + throws Exception { + List 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 moreData = dg.getData(mapForTemplate); + if( moreData != null ){ + mapForTemplate.putAll(moreData); + } + } + } + + + + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/MaintainDuplicatesObjectPropertyDataPostProcessor.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/MaintainDuplicatesObjectPropertyDataPostProcessor.java new file mode 100644 index 000000000..8ee416db6 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/MaintainDuplicatesObjectPropertyDataPostProcessor.java @@ -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 map) { + // no default data postprocessing defined yet + } + + @Override + public void process(List> 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 map : data) { + process(map); + } + } + +} diff --git a/webapp/web/WEB-INF/ontologies/app/menuload/displayTBOX.n3 b/webapp/web/WEB-INF/ontologies/app/menuload/displayTBOX.n3 index 0fc93da2c..a10188bf5 100644 --- a/webapp/web/WEB-INF/ontologies/app/menuload/displayTBOX.n3 +++ b/webapp/web/WEB-INF/ontologies/app/menuload/displayTBOX.n3 @@ -53,7 +53,6 @@ owl:ObjectProperty a owl:Class . - ########Data Properties######### ###Basic