updates for sparql data getter and updates to data getter utils

This commit is contained in:
hjkhjk54 2012-02-29 19:18:07 +00:00
parent eb1ff58879
commit 558985d542
5 changed files with 274 additions and 7 deletions

View file

@ -3,12 +3,20 @@ package edu.cornell.mannlib.vitro.webapp.utils.dataGetter;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.net.URLEncoder;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.List; import java.util.List;
import java.util.Map;
import javax.servlet.ServletContext;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; 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.Query;
import com.hp.hpl.jena.query.QueryExecution; import com.hp.hpl.jena.query.QueryExecution;
@ -17,13 +25,26 @@ import com.hp.hpl.jena.query.QueryFactory;
import com.hp.hpl.jena.query.QuerySolution; import com.hp.hpl.jena.query.QuerySolution;
import com.hp.hpl.jena.query.QuerySolutionMap; import com.hp.hpl.jena.query.QuerySolutionMap;
import com.hp.hpl.jena.query.ResultSet; 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.Model;
import com.hp.hpl.jena.rdf.model.RDFNode;
import com.hp.hpl.jena.rdf.model.Resource; import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.rdf.model.ResourceFactory; import com.hp.hpl.jena.rdf.model.ResourceFactory;
import com.hp.hpl.jena.shared.Lock;
import com.hp.hpl.jena.vocabulary.OWL; 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.controller.Controllers;
import edu.cornell.mannlib.vitro.webapp.controller.JsonServlet;
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.UrlBuilder;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.IndividualListController.PageRecord;
import edu.cornell.mannlib.vitro.webapp.dao.DisplayVocabulary; import edu.cornell.mannlib.vitro.webapp.dao.DisplayVocabulary;
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
import edu.cornell.mannlib.vitro.webapp.utils.pageDataGetter.PageDataGetterUtils; import edu.cornell.mannlib.vitro.webapp.utils.pageDataGetter.PageDataGetterUtils;
public class DataGetterUtils { public class DataGetterUtils {
@ -180,6 +201,23 @@ public class DataGetterUtils {
} }
throw new IllegalAccessException("No useful type defined for <" + dataGetterURI + ">"); throw new IllegalAccessException("No useful type defined for <" + dataGetterURI + ">");
} }
//Copied from PageDaoJena
static protected String nodeToString( RDFNode node ){
if( node == null ){
return "";
}else if( node.isLiteral() ){
Literal literal = node.asLiteral();
return literal.getLexicalForm();
}else if( node.isURIResource() ){
Resource resource = node.asResource();
return resource.getURI();
}else if( node.isAnon() ){
Resource resource = node.asResource();
return resource.getId().getLabelString(); //get b-node id
}else{
return "";
}
}
static final String prefixes = static final String prefixes =
"PREFIX rdf: <" + VitroVocabulary.RDF +"> \n" + "PREFIX rdf: <" + VitroVocabulary.RDF +"> \n" +
@ -187,6 +225,181 @@ public class DataGetterUtils {
"PREFIX xsd: <http://www.w3.org/2001/XMLSchema#> \n" + "PREFIX xsd: <http://www.w3.org/2001/XMLSchema#> \n" +
"PREFIX display: <" + DisplayVocabulary.DISPLAY_NS +"> \n"; "PREFIX display: <" + DisplayVocabulary.DISPLAY_NS +"> \n";
//This query is used in more than one place, so can be placed here
//An alternative is to have individuals for classes data getter extend classgroupdatagetter
//This currently assumes one class group uri per data getter, but this can be extended
/**
* For page data getter conversions
*/
/**
* Get Individual count for Solr query for intersection of multiple classes
*/
public static long getIndividualCountForIntersection(VitroRequest vreq, ServletContext context, List<String> classUris) {
return IndividualListController.getIndividualCount(classUris, vreq.getWebappDaoFactory().getIndividualDao(), context);
}
//Return data getter type to be employed in display model
public static String generateDataGetterTypeURI(String dataGetterClassName) {
return "java:" + dataGetterClassName;
}
public static final String getClassGroupForDataGetter(Model displayModel, String dataGetterURI) {
String classGroupUri = null;
QuerySolutionMap initBindings = new QuerySolutionMap();
initBindings.add("dataGetterURI", ResourceFactory.createResource(dataGetterURI));
int count = 0;
//Get the class group
Query dataGetterConfigurationQuery = QueryFactory.create(classGroupForDataGetterQuery) ;
displayModel.enterCriticalSection(Lock.READ);
try{
QueryExecution qexec = QueryExecutionFactory.create(
dataGetterConfigurationQuery, displayModel, initBindings) ;
ResultSet res = qexec.execSelect();
try{
while( res.hasNext() ){
count++;
QuerySolution soln = res.next();
//model is OPTIONAL
RDFNode node = soln.getResource("classGroupUri");
if( node != null && node.isURIResource() ){
classGroupUri = node.asResource().getURI();
}else{
classGroupUri = null;
}
}
}finally{ qexec.close(); }
}finally{ displayModel.leaveCriticalSection(); }
return classGroupUri;
}
/**
* Process results related to VClass or vclasses. Handles both single and multiple vclasses being sent.
*/
public static JSONObject processVclassResultsJSON(Map<String, Object> map, VitroRequest vreq, boolean multipleVclasses) {
JSONObject rObj = new JSONObject();
VClass vclass=null;
try {
// Properties from ontologies used by VIVO - should not be in vitro
DataProperty fNameDp = (new DataProperty());
fNameDp.setURI("http://xmlns.com/foaf/0.1/firstName");
DataProperty lNameDp = (new DataProperty());
lNameDp.setURI("http://xmlns.com/foaf/0.1/lastName");
DataProperty preferredTitleDp = (new DataProperty());
preferredTitleDp.setURI("http://vivoweb.org/ontology/core#preferredTitle");
if( log.isDebugEnabled() ){
@SuppressWarnings("unchecked")
Enumeration<String> e = vreq.getParameterNames();
while(e.hasMoreElements()){
String name = (String)e.nextElement();
log.debug("parameter: " + name);
for( String value : vreq.getParameterValues(name) ){
log.debug("value for " + name + ": '" + value + "'");
}
}
}
//need an unfiltered dao to get firstnames and lastnames
WebappDaoFactory fullWdf = vreq.getFullWebappDaoFactory();
String[] vitroClassIdStr = vreq.getParameterValues("vclassId");
if ( vitroClassIdStr != null && vitroClassIdStr.length > 0){
for(String vclassId: vitroClassIdStr) {
vclass = vreq.getWebappDaoFactory().getVClassDao().getVClassByURI(vclassId);
if (vclass == null) {
log.error("Couldn't retrieve vclass ");
throw new Exception ("Class " + vclassId + " not found");
}
}
}else{
log.error("parameter vclassId URI parameter expected ");
throw new Exception("parameter vclassId URI parameter expected ");
}
List<String> vclassIds = Arrays.asList(vitroClassIdStr);
//if single vclass expected, then include vclass. This relates to what the expected behavior is, not size of list
if(!multipleVclasses) {
//currently used for ClassGroupPage
rObj.put("vclass",
new JSONObject().put("URI",vclass.getURI())
.put("name",vclass.getName()));
} else {
//For now, utilize very last VClass (assume that that is the one to be employed)
//TODO: Find more general way of dealing with this
//put multiple ones in?
if(vclassIds.size() > 0) {
int numberVClasses = vclassIds.size();
vclass = vreq.getWebappDaoFactory().getVClassDao().getVClassByURI(vclassIds.get(numberVClasses - 1));
rObj.put("vclass", new JSONObject().put("URI",vclass.getURI())
.put("name",vclass.getName()));
}
// rObj.put("vclasses", new JSONObject().put("URIs",vitroClassIdStr)
// .put("name",vclass.getName()));
}
if (vclass != null) {
rObj.put("totalCount", map.get("totalCount"));
rObj.put("alpha", map.get("alpha"));
List<Individual> inds = (List<Individual>)map.get("entities");
log.debug("Number of individuals returned from request: " + inds.size());
JSONArray jInds = new JSONArray();
for(Individual ind : inds ){
JSONObject jo = new JSONObject();
jo.put("URI", ind.getURI());
jo.put("label",ind.getRdfsLabel());
jo.put("name",ind.getName());
jo.put("thumbUrl", ind.getThumbUrl());
jo.put("imageUrl", ind.getImageUrl());
jo.put("profileUrl", UrlBuilder.getIndividualProfileUrl(ind, vreq));
jo.put("mostSpecificTypes", JsonServlet.getMostSpecificTypes(ind,fullWdf));
jo.put("preferredTitle", JsonServlet.getDataPropertyValue(ind, preferredTitleDp, fullWdf));
jInds.put(jo);
}
rObj.put("individuals", jInds);
JSONArray wpages = new JSONArray();
//Made sure that PageRecord here is SolrIndividualListController not IndividualListController
List<PageRecord> pages = (List<PageRecord>)map.get("pages");
for( PageRecord pr: pages ){
JSONObject p = new JSONObject();
p.put("text", pr.text);
p.put("param", pr.param);
p.put("index", pr.index);
wpages.put( p );
}
rObj.put("pages",wpages);
JSONArray jletters = new JSONArray();
List<String> letters = Controllers.getLetters();
for( String s : letters){
JSONObject jo = new JSONObject();
jo.put("text", s);
jo.put("param", "alpha=" + URLEncoder.encode(s, "UTF-8"));
jletters.put( jo );
}
rObj.put("letters", jletters);
}
} catch(Exception ex) {
log.error("Error occurred in processing JSON object", ex);
}
return rObj;
}
private static final String forClassGroupURI = "<" + DisplayVocabulary.FOR_CLASSGROUP + ">";
private static final String classGroupForDataGetterQuery =
"PREFIX display: <" + DisplayVocabulary.DISPLAY_NS +"> \n" +
"SELECT ?classGroupUri WHERE { \n" +
" ?dataGetterUri "+forClassGroupURI+" ?classGroupUri . \n" +
"}";
} }

View file

@ -206,14 +206,14 @@ public class SparqlQueryDataGetter extends DataGetterBase implements DataGetter{
public static final String defaultVarNameForResults = "results"; public static final String defaultVarNameForResults = "results";
/** /**
* Query to get the definition of the SparqlDataGetter for a given URI. * Query to get the definition of the SparqlDataGetter for a given data getter URI.
*/ */
private static final String dataGetterQuery = private static final String dataGetterQuery =
"PREFIX display: <" + DisplayVocabulary.DISPLAY_NS +"> \n" + "PREFIX display: <" + DisplayVocabulary.DISPLAY_NS +"> \n" +
"SELECT ?query ?saveToVar ?model WHERE { \n" + "SELECT ?query ?saveToVar ?model WHERE { \n" +
" ?pageUri "+queryPropertyURI+" ?query . \n" + " ?dataGetterUri "+queryPropertyURI+" ?query . \n" +
" OPTIONAL{ ?pageUri "+saveToVarPropertyURI+" ?saveToVar } \n " + " OPTIONAL{ ?dataGetterUri "+saveToVarPropertyURI+" ?saveToVar } \n " +
" OPTIONAL{ ?pageUri "+queryModelPropertyURI+" ?queryModel } \n" + " OPTIONAL{ ?dataGetterUri "+queryModelPropertyURI+" ?model } \n" +
"}"; "}";

View file

@ -102,7 +102,13 @@ owl:versionInfo
<http://vitro.mannlib.cornell.edu/ontologies/display/1.1#usesDataGetterClass> <http://vitro.mannlib.cornell.edu/ontologies/display/1.1#usesDataGetterClass>
a owl:DatatypeProperty . a owl:DatatypeProperty .
###Custom data getters that may or may not be associated with a page use the following relationships
###E.g. sparql data getters can specify the query to be used as well as what variable in the template
###should store the results
<http://vitro.mannlib.cornell.edu/ontologies/display/1.1#saveToVar>
a owl:DatatypeProperty .
<http://vitro.mannlib.cornell.edu/ontologies/display/1.1#query>
a owl:DatatypeProperty .
######### Object Properties######### ######### Object Properties#########
###Basic ###Basic
rdfs:range rdfs:range
@ -173,4 +179,7 @@ owl:topObjectProperty
<http://vitro.mannlib.cornell.edu/ontologies/display/1.1#restrictResultsByClass> <http://vitro.mannlib.cornell.edu/ontologies/display/1.1#restrictResultsByClass>
a owl:ObjectProperty . a owl:ObjectProperty .
###Custom data getters that may or may not be associated with a page use the following relationships
###E.g. sparql data getters can specify what model to use for querying
<http://vitro.mannlib.cornell.edu/ontologies/display/1.1#queryModel>
a owl:ObjectProperty .

View file

@ -0,0 +1,13 @@
.resultRow {
float:none;
clear:both;
}
.resultCell {
float:left;
border:1px solid #000000;
}
.resultHeading {
font-weight:bold;
}

View file

@ -0,0 +1,32 @@
<#--Save to variable is sparqlResults -->
<#assign resultsExist = false/>
<#if sparqlResults?has_content>
<#assign resultsExist = true/>
</#if>
<h3>Sparql Query Results</h3>
<#if resultsExist>
<#assign numberRows = sparqlResults?size/>
<#assign firstRow = false/>
<#list sparqlResults as resultRow>
<#assign resultKeys = resultRow?keys />
<#if firstRow = false>
<div class="resultHeading resultRow">
<#list resultKeys as resultKey>
<div class="resultCell">${resultKey}</div>
</#list>
</div>
<#assign firstRow = true/>
</#if>
<div class="resultRow">
<#list resultKeys as resultKey>
<div class="resultCell">${resultRow[resultKey]}</div>
</#list>
</div>
</#list>
<#else>
No results were returned.
</#if>
${stylesheets.add('<link rel="stylesheet" href="${urls.base}/css/menupage/sparqlresults.css" />')}