Changes for NIHVIVO-2231 and NIHVIVO-2664: setting up menu page editing and retrieval of individuals for class intersections

This commit is contained in:
hjkhjk54 2011-06-08 21:14:52 +00:00
parent 91db1ad147
commit 9214b285a5
23 changed files with 501 additions and 66 deletions

View file

@ -175,9 +175,28 @@ public class IndividualListController extends FreemarkerHttpServlet {
public static Map<String,Object> getResultsForVClass(String vclassURI, int page, String alpha, IndividualDao indDao, ServletContext context) public static Map<String,Object> getResultsForVClass(String vclassURI, int page, String alpha, IndividualDao indDao, ServletContext context)
throws CorruptIndexException, IOException, ServletException{ throws CorruptIndexException, IOException, ServletException{
Map<String,Object> rvMap = new HashMap<String,Object>(); Map<String,Object> rvMap = new HashMap<String,Object>();
try{
//make lucene query for this rdf:type //make lucene query for this rdf:type
Query query = getQuery(vclassURI, alpha); List<String> classUris = new ArrayList<String>();
classUris.add(vclassURI);
Query query = getQuery(classUris, alpha);
rvMap = getResultsForVClassQuery(query, page, alpha, indDao, context);
List<Individual> individuals = (List<Individual>) rvMap.get("entities");
if (individuals == null)
log.debug("entities list is null for vclass " + vclassURI );
} catch(Throwable th) {
log.error("An error occurred retrieving results for vclass query", th);
}
return rvMap;
}
/*
* This method includes what was formerly a part of the method above, allowing for refactoring of code
* to use for a different number fo classes
*/
public static Map<String,Object> getResultsForVClassQuery(Query query, int page, String alpha, IndividualDao indDao, ServletContext context)
throws CorruptIndexException, IOException, ServletException{
Map<String,Object> rvMap = new HashMap<String,Object>();
//execute lucene query for individuals of the specified type //execute lucene query for individuals of the specified type
IndexSearcher index = LuceneIndexFactory.getIndexSearcher(context); IndexSearcher index = LuceneIndexFactory.getIndexSearcher(context);
@ -237,20 +256,43 @@ public class IndividualListController extends FreemarkerHttpServlet {
rvMap.put("totalCount", size); rvMap.put("totalCount", size);
rvMap.put("entities",individuals); rvMap.put("entities",individuals);
if (individuals == null)
log.debug("entities list is null for vclass " + vclassURI );
return rvMap; return rvMap;
} }
private static BooleanQuery getQuery(String vclassUri, String alpha){
public static Map<String,Object> getResultsForVClassIntersections(List<String> vclassURIs, int page, String alpha, IndividualDao indDao, ServletContext context)
throws CorruptIndexException, IOException, ServletException{
Map<String,Object> rvMap = new HashMap<String,Object>();
try{
//make lucene query for multiple rdf types
Query query = getQuery(vclassURIs, alpha);
//get results corresponding to this query
rvMap = getResultsForVClassQuery(query, page, alpha, indDao, context);
List<Individual> individuals = (List<Individual>) rvMap.get("entities");
if (individuals == null)
log.debug("entities list is null for vclass " + vclassURIs.toString() );
} catch(Throwable th) {
log.error("Error retrieving individuals corresponding to intersection multiple classes." + vclassURIs.toString());
}
return rvMap;
}
/*
* This method creates a query to search for terms with rdf type corresponding to vclass Uri.
* The original version allowed only for one class URI but needed to be extended to enable multiple
* vclass Uris to be passed
*/
private static BooleanQuery getQuery(List<String>vclassUris, String alpha){
BooleanQuery query = new BooleanQuery(); BooleanQuery query = new BooleanQuery();
try{ try{
//query term for rdf:type //query term for rdf:type - multiple types possible
for(String vclassUri: vclassUris) {
query.add( query.add(
new TermQuery( new Term(Entity2LuceneDoc.term.RDFTYPE, vclassUri)), new TermQuery( new Term(Entity2LuceneDoc.term.RDFTYPE, vclassUri)),
BooleanClause.Occur.MUST ); BooleanClause.Occur.MUST );
}
//Add alpha filter if it is needed //Add alpha filter if it is needed
Query alphaQuery = null; Query alphaQuery = null;
if( alpha != null && !"".equals(alpha) && alpha.length() == 1){ if( alpha != null && !"".equals(alpha) && alpha.length() == 1){

View file

@ -23,7 +23,7 @@ import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.Tem
import edu.cornell.mannlib.vitro.webapp.utils.pageDataGetter.BrowseDataGetter; import edu.cornell.mannlib.vitro.webapp.utils.pageDataGetter.BrowseDataGetter;
import edu.cornell.mannlib.vitro.webapp.utils.pageDataGetter.PageDataGetter; import edu.cornell.mannlib.vitro.webapp.utils.pageDataGetter.PageDataGetter;
import edu.cornell.mannlib.vitro.webapp.utils.pageDataGetter.ClassGroupPageData; import edu.cornell.mannlib.vitro.webapp.utils.pageDataGetter.ClassGroupPageData;
import edu.cornell.mannlib.vitro.webapp.utils.pageDataGetter.ClassIntersectionDataGetter;
/** /**
* Controller for getting data for pages defined in the display model. * Controller for getting data for pages defined in the display model.
* *
@ -112,7 +112,10 @@ public class PageController extends FreemarkerHttpServlet{
return Collections.emptyMap(); return Collections.emptyMap();
PageDataGetter getter = getPageDataGetterMap(getServletContext()).get(type); PageDataGetter getter = getPageDataGetterMap(getServletContext()).get(type);
//For now hardcoding, check to see if data getter included within
if((String)page.get("datagetter") != null) {
getter = new ClassIntersectionDataGetter();
}
if( getter != null ){ if( getter != null ){
try{ try{
return getter.getData(getServletContext(), vreq, pageUri, page, type); return getter.getData(getServletContext(), vreq, pageUri, page, type);
@ -177,6 +180,12 @@ public class PageController extends FreemarkerHttpServlet{
getPageDataGetterMap(context).put(cgpd.getType(), cgpd); getPageDataGetterMap(context).put(cgpd.getType(), cgpd);
BrowseDataGetter bdg = new BrowseDataGetter(); BrowseDataGetter bdg = new BrowseDataGetter();
getPageDataGetterMap(context).put(bdg.getType(), bdg); getPageDataGetterMap(context).put(bdg.getType(), bdg);
//TODO: Check if can include by type here
ClassIntersectionDataGetter cidg = new ClassIntersectionDataGetter();
getPageDataGetterMap(context).put(cidg.getType(), cidg);
} }
} }
} }

View file

@ -270,6 +270,12 @@ public class UrlBuilder {
public static String getPath(Route route, ParamMap params) { public static String getPath(Route route, ParamMap params) {
return getPath(route.path(), params); return getPath(route.path(), params);
} }
//Adding method to allow for checking for special parameters
public static String getIndividualProfileUrl(String individualUri, VitroRequest vreq) {
Individual individual = new IndividualImpl(individualUri);
return getIndividualProfileUrl(individual, individualUri, vreq);
}
public static String getIndividualProfileUrl(String individualUri, WebappDaoFactory wadf) { public static String getIndividualProfileUrl(String individualUri, WebappDaoFactory wadf) {
Individual individual = new IndividualImpl(individualUri); Individual individual = new IndividualImpl(individualUri);
@ -281,6 +287,19 @@ public class UrlBuilder {
return getIndividualProfileUrl(individual, individualUri, wadf); return getIndividualProfileUrl(individual, individualUri, wadf);
} }
//Trying first with using a form of the method that includes the vitro request
private static String getIndividualProfileUrl(Individual individual, String individualUri, VitroRequest vreq) {
WebappDaoFactory wadf = vreq.getWebappDaoFactory();
String profileUrl = getIndividualProfileUrl(individual, individualUri, wadf);
if(profileUrl != null) {
HashMap<String, String> specialParams = getSpecialParams(vreq);
if(specialParams.size() != 0) {
profileUrl = addParams(profileUrl, new ParamMap(specialParams));
}
}
return profileUrl;
}
private static String getIndividualProfileUrl(Individual individual, String individualUri, WebappDaoFactory wadf) { private static String getIndividualProfileUrl(Individual individual, String individualUri, WebappDaoFactory wadf) {
String profileUrl = null; String profileUrl = null;
try { try {
@ -346,4 +365,32 @@ public class UrlBuilder {
return decodedUrl; return decodedUrl;
} }
//To be used in different property templates so placing method for reuse here
//Check if special params included, specifically for menu management and other models
public static HashMap<String,String> getSpecialParams(VitroRequest vreq) {
HashMap<String,String> specialParams = new HashMap<String, String>();
if(vreq != null) {
//this parameter is sufficient to switch to menu model
String useMenuModelParam = vreq.getParameter("usemenumodel");
//the parameters below allow for using a different model
String useMainModelUri = vreq.getParameter("usemodel");
String useTboxModelUri = vreq.getParameter("usetboxmodel");
String useDisplayModelUri = vreq.getParameter("usedisplaymodel");
if(useMenuModelParam != null && !useMenuModelParam.isEmpty()) {
specialParams.put("usemenumodel", useMenuModelParam);
}
else if(useMainModelUri != null && !useMainModelUri.isEmpty()) {
specialParams.put("usemodel", useMainModelUri);
if(useTboxModelUri != null && !useTboxModelUri.isEmpty()){
specialParams.put("usetboxmodel", useTboxModelUri);
}
if(useDisplayModelUri != null && !useDisplayModelUri.isEmpty()) {
specialParams.put("usedisplaymodel", useDisplayModelUri);
}
}
}
return specialParams;
}
} }

View file

@ -28,10 +28,12 @@ public class DisplayVocabulary {
public static final String PAGE_TYPE = NS + "Page"; public static final String PAGE_TYPE = NS + "Page";
public static final String HOME_PAGE_TYPE = NS + "HomePage"; public static final String HOME_PAGE_TYPE = NS + "HomePage";
public static final String CLASSGROUP_PAGE_TYPE = NS + "ClassGroupPage"; public static final String CLASSGROUP_PAGE_TYPE = NS + "ClassGroupPage";
//Including for now, can take out later
public static final String CLASSINTERSECTION_PAGE_TYPE = NS + "ClassIntersectionPage";
/* Object Properties */ /* Object Properties */
public static final String FOR_CLASSGROUP = NS + "forClassGroup"; public static final String FOR_CLASSGROUP = NS + "forClassGroup";
public static final String CLASS_INTERSECTION = NS + "intersectsWithClass";
/* Data Properties */ /* Data Properties */
public static final DatatypeProperty URL_MAPPING = m_model.createDatatypeProperty(NS + "urlMapping"); public static final DatatypeProperty URL_MAPPING = m_model.createDatatypeProperty(NS + "urlMapping");
public static final String TITLE = NS + "title"; public static final String TITLE = NS + "title";

View file

@ -3,7 +3,7 @@
package edu.cornell.mannlib.vitro.webapp.dao; package edu.cornell.mannlib.vitro.webapp.dao;
import java.util.Map; import java.util.Map;
import java.util.List;
public interface PageDao { public interface PageDao {
Map<String, Object> getPage(String pageUri); Map<String, Object> getPage(String pageUri);
@ -22,4 +22,6 @@ public interface PageDao {
String getHomePageUri(); String getHomePageUri();
String getClassGroupPage(String pageUri); String getClassGroupPage(String pageUri);
List<String> getClassIntersections(String pageUri);
} }

View file

@ -38,6 +38,7 @@ public class PageDaoJena extends JenaBaseDao implements PageDao {
static protected Query pageMappingsQuery; static protected Query pageMappingsQuery;
static protected Query homePageUriQuery; static protected Query homePageUriQuery;
static protected Query classGroupPageQuery; static protected Query classGroupPageQuery;
static protected Query classIntersectionPageQuery;
static final String prefixes = static final String prefixes =
"PREFIX rdf: <" + VitroVocabulary.RDF +"> \n" + "PREFIX rdf: <" + VitroVocabulary.RDF +"> \n" +
@ -78,6 +79,10 @@ public class PageDaoJena extends JenaBaseDao implements PageDao {
prefixes + "\n" + prefixes + "\n" +
"SELECT ?classGroup WHERE { ?pageUri <" + DisplayVocabulary.FOR_CLASSGROUP + "> ?classGroup . }"; "SELECT ?classGroup WHERE { ?pageUri <" + DisplayVocabulary.FOR_CLASSGROUP + "> ?classGroup . }";
static final protected String classIntersectionPageQueryString =
prefixes + "\n" +
"SELECT ?classIntersection WHERE { ?pageUri <" + DisplayVocabulary.CLASS_INTERSECTION + "> ?classIntersection . }";
static{ static{
try{ try{
pageQuery=QueryFactory.create(pageQueryString); pageQuery=QueryFactory.create(pageQueryString);
@ -109,6 +114,12 @@ public class PageDaoJena extends JenaBaseDao implements PageDao {
log.error("could not create SPARQL query for classGroupPageQuery " + th.getMessage()); log.error("could not create SPARQL query for classGroupPageQuery " + th.getMessage());
log.error(classGroupPageQueryString); log.error(classGroupPageQueryString);
} }
try{
classIntersectionPageQuery=QueryFactory.create(classIntersectionPageQueryString);
}catch(Throwable th){
log.error("could not create SPARQL query for classIntersectionPageQuery " + th.getMessage());
log.error(classIntersectionPageQueryString);
}
} }
public PageDaoJena(WebappDaoFactoryJena wadf) { public PageDaoJena(WebappDaoFactoryJena wadf) {
@ -240,6 +251,30 @@ public class PageDaoJena extends JenaBaseDao implements PageDao {
return classGroupsForPage.get(0); return classGroupsForPage.get(0);
} }
/**
* Get the names of the classes for class intersection. Multiple classes possible.
*/
public List<String> getClassIntersections(String pageUri) {
List<String> classIntersections = new ArrayList<String>();
QuerySolutionMap initialBindings = new QuerySolutionMap();
initialBindings.add("pageUri", ResourceFactory.createResource(pageUri));
Model displayModel = getOntModelSelector().getDisplayModel();
QueryExecution qexec = QueryExecutionFactory.create( classIntersectionPageQuery, displayModel , initialBindings);
ResultSet resultSet = qexec.execSelect();
while(resultSet.hasNext()){
QuerySolution soln = resultSet.next();
classIntersections.add( nodeToString(soln.get("classIntersection")) );
}
if( classIntersections.size() == 0 ){
log.debug("No class intersections info defined in display model for "+ pageUri);
return null;
}
return classIntersections;
}
/* ****************************************************************************** */ /* ****************************************************************************** */

View file

@ -635,8 +635,24 @@ public class WebappDaoFactoryJena implements WebappDaoFactory {
//Method for using special model for webapp dao factory, such as display model //Method for using special model for webapp dao factory, such as display model
//This is still in flux, am checking in to allow others to experiment //This is still in flux, am checking in to allow others to experiment
public void setSpecialDataModel(OntModel specialModel, OntModel specialTboxModel) { public boolean isUsingSpecialModel = false;
WebappDaoFactoryJena specialWadfj = new WebappDaoFactoryJena(specialModel); public void setSpecialDataModel(OntModel specialModel, OntModel specialTboxModel, OntModel specialDisplayModel) {
//Set up model selector for the new webapp dao factory object with the input model
//The selector is used by the object property dao, therefore should be set up even though we
//use the new webapp dao factory object to generate portions to overwrite the regular webapp dao factory
OntModelSelectorImpl specialSelector = new OntModelSelectorImpl();
specialSelector.setFullModel(specialModel);
specialSelector.setApplicationMetadataModel(specialModel);
specialSelector.setDisplayModel(specialDisplayModel);
specialSelector.setTBoxModel(specialTboxModel);
specialSelector.setABoxModel(specialModel);
specialSelector.setUserAccountsModel(specialModel);
//although we're only use part of the new wadf and copy over below, the object property dao
//utilizes methods that will employ the display model returned from the simple ontmodel selector
//so if the object property dao is to be copied over we need to ensure we have the correct display model
//and tbox model
WebappDaoFactoryJena specialWadfj = new WebappDaoFactoryJena(specialSelector);
entityWebappDao = specialWadfj.getIndividualDao(); entityWebappDao = specialWadfj.getIndividualDao();
keys2EntsDao = specialWadfj.getKeys2EntsDao(); keys2EntsDao = specialWadfj.getKeys2EntsDao();
keywordDao = specialWadfj.getKeywordDao(); keywordDao = specialWadfj.getKeywordDao();
@ -646,8 +662,11 @@ public class WebappDaoFactoryJena implements WebappDaoFactory {
//To allow for testing, add a property group, this will allow //To allow for testing, add a property group, this will allow
//the unassigned group method section to be executed and main Image to be assigned to that group //the unassigned group method section to be executed and main Image to be assigned to that group
//otherwise the dummy group does not allow for the unassigned group to be executed //otherwise the dummy group does not allow for the unassigned group to be executed
propertyGroupDao = specialWadfj.getPropertyGroupDao(); propertyGroupDao = specialWadfj.getPropertyGroupDao();
objectPropertyDao = specialWadfj.getObjectPropertyDao();
objectPropertyStatementDao = specialWadfj.getObjectPropertyStatementDao();
dataPropertyDao = specialWadfj.getDataPropertyDao();
dataPropertyStatementDao = specialWadfj.getDataPropertyStatementDao();
PropertyGroup pgtest = new edu.cornell.mannlib.vitro.webapp.beans.PropertyGroup(); PropertyGroup pgtest = new edu.cornell.mannlib.vitro.webapp.beans.PropertyGroup();
pgtest.setName("testname"); pgtest.setName("testname");
pgtest.setDisplayRank(1); pgtest.setDisplayRank(1);
@ -657,7 +676,14 @@ public class WebappDaoFactoryJena implements WebappDaoFactory {
if(ontModelSelector instanceof OntModelSelectorImpl) { if(ontModelSelector instanceof OntModelSelectorImpl) {
OntModelSelectorImpl omsImpl = (OntModelSelectorImpl) ontModelSelector; OntModelSelectorImpl omsImpl = (OntModelSelectorImpl) ontModelSelector;
omsImpl.setTBoxModel(specialTboxModel); omsImpl.setTBoxModel(specialTboxModel);
omsImpl.setDisplayModel(specialDisplayModel);
} }
else if(ontModelSelector instanceof SimpleOntModelSelector) {
SimpleOntModelSelector omsImpl = (SimpleOntModelSelector) ontModelSelector;
omsImpl.setTBoxModel(specialTboxModel);
omsImpl.setDisplayModel(specialDisplayModel);
}
isUsingSpecialModel = true;
} }
} }

View file

@ -22,6 +22,7 @@ import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.ontology.OntModelSpec; import com.hp.hpl.jena.ontology.OntModelSpec;
import com.hp.hpl.jena.query.Dataset; import com.hp.hpl.jena.query.Dataset;
import com.hp.hpl.jena.rdf.model.ModelFactory; import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.Model;
import edu.cornell.mannlib.vitro.webapp.auth.identifier.RequestIdentifiers; import edu.cornell.mannlib.vitro.webapp.auth.identifier.RequestIdentifiers;
import edu.cornell.mannlib.vitro.webapp.auth.policy.ServletPolicyList; import edu.cornell.mannlib.vitro.webapp.auth.policy.ServletPolicyList;
@ -36,6 +37,7 @@ import edu.cornell.mannlib.vitro.webapp.dao.filtering.filters.VitroFilters;
import edu.cornell.mannlib.vitro.webapp.dao.jena.WebappDaoFactoryJena; import edu.cornell.mannlib.vitro.webapp.dao.jena.WebappDaoFactoryJena;
import edu.cornell.mannlib.vitro.webapp.servlet.setup.JenaDataSourceSetupBase; import edu.cornell.mannlib.vitro.webapp.servlet.setup.JenaDataSourceSetupBase;
import org.apache.commons.dbcp.BasicDataSource; import org.apache.commons.dbcp.BasicDataSource;
/** /**
* This sets up several objects in the Request scope for each * This sets up several objects in the Request scope for each
* incoming HTTP request. This is done in a Filter so * incoming HTTP request. This is done in a Filter so
@ -199,24 +201,48 @@ public class VitroRequestPrep implements Filter {
} }
//check if special model - this is for enabling the use of a different model for menu management //check if special model - this is for enabling the use of a different model for menu management
//Also enables the use of a completely different model and tbox if uris are passed
private void checkForSpecialWDF(VitroRequest vreq, WebappDaoFactory wadf) { private void checkForSpecialWDF(VitroRequest vreq, WebappDaoFactory wadf) {
if(vreq.getParameter("test") != null) { String useMenuModelParam = vreq.getParameter("usemenumodel");
boolean useMenu = (useMenuModelParam != null);
//other parameters to be passed in in case want to use specific models
String useMainModelUri = vreq.getParameter("usemodel");
String useTboxModelUri = vreq.getParameter("usetboxmodel");
String useDisplayModelUri = vreq.getParameter("usedisplaymodel");
if(useMenu || (useMainModelUri != null && !useMainModelUri.isEmpty() && useTboxModelUri != null && !useTboxModelUri.isEmpty())) {
if(wadf instanceof WebappDaoFactoryJena) { if(wadf instanceof WebappDaoFactoryJena) {
WebappDaoFactoryJena wadfj = (WebappDaoFactoryJena) wadf; WebappDaoFactoryJena wadfj = (WebappDaoFactoryJena) wadf;
OntModel testDisplayModel = (OntModel) _context.getAttribute("displayOntModel"); OntModel useMainOntModel = null, useTboxOntModel = null, useDisplayOntModel = null;
Model tboxModel = null, displayModel = null;
//Hardcoding tbox model uri for now
String tboxModelUri = "http://vitro.mannlib.cornell.edu/default/vitro-kb-displayMetadataTBOX";
BasicDataSource bds = JenaDataSourceSetupBase.getApplicationDataSource(_context); BasicDataSource bds = JenaDataSourceSetupBase.getApplicationDataSource(_context);
//Model dbPlainModel = JenaDataSourceSetupBase.makeDBModelFromConfigurationProperties(tboxModelUri, OntModelSpec.OWL_MEM, _context);
String dbType = ConfigurationProperties.getBean(_context).getProperty( // database type String dbType = ConfigurationProperties.getBean(_context).getProperty( // database type
"VitroConnection.DataSource.dbtype", "MySQL"); "VitroConnection.DataSource.dbtype", "MySQL");
com.hp.hpl.jena.rdf.model.Model displayTboxModel = JenaDataSourceSetupBase.makeDBModel(bds, tboxModelUri, OntModelSpec.OWL_MEM, JenaDataSourceSetupBase.TripleStoreType.RDB, dbType, _context); if(useMenu) {
System.out.println("Checking what the display tbox model is returning"); //if using special models for menu management, get main menu model from context and set tbox and display uris to be used
displayTboxModel.write(System.out, "N3"); useMainOntModel = (OntModel) _context.getAttribute("displayOntModel");
OntModel displayTboxOntModel = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM, displayTboxModel); //Hardcoding tbox model uri for now
useTboxModelUri = "http://vitro.mannlib.cornell.edu/default/vitro-kb-displayMetadataTBOX";
useDisplayModelUri = "http://vitro.mannlib.cornell.edu/default/vitro-kb-displayMetadata-displayModel";
} else {
//If main model uri passed as parameter then retrieve model from parameter
Model mainModel = JenaDataSourceSetupBase.makeDBModel(bds, useMainModelUri, OntModelSpec.OWL_MEM, JenaDataSourceSetupBase.TripleStoreType.RDB, dbType, _context);
//if this uri exists and model exists, then set up ont model version
if(mainModel != null) {
useMainOntModel = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM, mainModel);
}
}
wadfj.setSpecialDataModel(testDisplayModel, displayTboxOntModel); tboxModel = JenaDataSourceSetupBase.makeDBModel(bds, useTboxModelUri, OntModelSpec.OWL_MEM, JenaDataSourceSetupBase.TripleStoreType.RDB, dbType, _context);
System.out.println("Checking what the display tbox model is returning");
tboxModel.write(System.out, "N3");
useTboxOntModel = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM, tboxModel);
//Set "display model" for display model
displayModel = JenaDataSourceSetupBase.makeDBModel(bds, useDisplayModelUri, OntModelSpec.OWL_MEM, JenaDataSourceSetupBase.TripleStoreType.RDB, dbType, _context);
useDisplayOntModel = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM, displayModel);
//Set special model for wadfj
if(useMainOntModel != null) {
wadfj.setSpecialDataModel(useMainOntModel, useTboxOntModel, useDisplayOntModel);
}
} }
} }
} }

View file

@ -0,0 +1,126 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.utils.pageDataGetter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
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.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.dao.DisplayVocabulary;
import edu.cornell.mannlib.vitro.webapp.dao.jena.VClassGroupCache;
import edu.cornell.mannlib.vitro.webapp.web.templatemodels.VClassGroupTemplateModel;
import edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual.ListedIndividualTemplateModel;
import freemarker.ext.beans.BeansWrapper;
import freemarker.template.TemplateModel;
/**
* This will pass these variables to the template:
* classGroupUri: uri of the classgroup associated with this page.
* vClassGroup: a data structure that is the classgroup associated with this page.
*/
public class ClassIntersectionDataGetter implements PageDataGetter{
private static final Log log = LogFactory.getLog(ClassIntersectionDataGetter.class);
public Map<String,Object> getData(ServletContext context, VitroRequest vreq, String pageUri, Map<String, Object> page, String type ){
HashMap<String, Object> data = new HashMap<String,Object>();
List<String> classIntersections = vreq.getWebappDaoFactory().getPageDao().getClassIntersections(pageUri);
data.put("classIntersections", classIntersections);
//Use Individual List Controller to get all the individuals and related data
String alpha = IndividualListController.getAlphaParameter(vreq);
int pageParam = IndividualListController.getPageParameter(vreq);
try{
Map<String, Object> results = IndividualListController.getResultsForVClassIntersections(classIntersections, pageParam, alpha, vreq.getWebappDaoFactory().getIndividualDao(), context);
data.putAll(results);
//NOTE: Below is copied from Individual List Controller's processing as some of these are used in the template
//below may not be necessary if using a different template
List<Individual> inds = (List<Individual>)data.get("entities");
List<ListedIndividualTemplateModel> indsTm = new ArrayList<ListedIndividualTemplateModel>();
for(Individual ind : inds ){
indsTm.add(new ListedIndividualTemplateModel(ind,vreq));
}
data.put("individuals", indsTm);
List<TemplateModel> wpages = new ArrayList<TemplateModel>();
List<PageRecord> pages = (List<PageRecord>)data.get("pages");
BeansWrapper wrapper = new BeansWrapper();
for( PageRecord pr: pages ){
wpages.add( wrapper.wrap(pr) );
}
data.put("rdfUrl", vreq.getContextPath()+"/listrdf/");
} catch(Exception ex) {
log.error("An error occurred retrieving Vclass Intersection individuals", ex);
}
//TODO: Check if need class group at all here?
//data.put("vClassGroup", group); //may put null
return data;
}
public static VClassGroupTemplateModel getClassGroup(String classGroupUri, ServletContext context, VitroRequest vreq){
VClassGroupCache vcgc = VClassGroupCache.getVClassGroupCache(context);
List<VClassGroup> vcgList = vcgc.getGroups();
VClassGroup group = null;
for( VClassGroup vcg : vcgList){
if( vcg.getURI() != null && vcg.getURI().equals(classGroupUri)){
group = vcg;
break;
}
}
if( classGroupUri != null && !classGroupUri.isEmpty() && group == null ){
/*This could be for two reasons: one is that the classgroup doesn't exist
* The other is that there are no individuals in any of the classgroup's classes */
group = vreq.getWebappDaoFactory().getVClassGroupDao().getGroupByURI(classGroupUri);
if( group != null ){
List<VClassGroup> vcgFullList = vreq.getWebappDaoFactory().getVClassGroupDao()
.getPublicGroupsWithVClasses(false, true, false);
for( VClassGroup vcg : vcgFullList ){
if( classGroupUri.equals(vcg.getURI()) ){
group = vcg;
break;
}
}
if( group == null ){
log.error("Cannot get classgroup '" + classGroupUri + "'");
return null;
}else{
setAllClassCountsToZero(group);
}
}else{
log.error("classgroup " + classGroupUri + " does not exist in the system");
return null;
}
}
return new VClassGroupTemplateModel(group);
}
public String getType(){
return DisplayVocabulary.CLASSINTERSECTION_PAGE_TYPE;
}
protected static void setAllClassCountsToZero(VClassGroup vcg){
for(VClass vc : vcg){
vc.setEntityCount(0);
}
}
}

View file

@ -27,7 +27,7 @@ public class IndividualProfileUrlMethod extends BaseTemplateMethodModel {
Environment env = Environment.getCurrentEnvironment(); Environment env = Environment.getCurrentEnvironment();
HttpServletRequest request = (HttpServletRequest) env.getCustomAttribute("request"); HttpServletRequest request = (HttpServletRequest) env.getCustomAttribute("request");
VitroRequest vreq = new VitroRequest(request); VitroRequest vreq = new VitroRequest(request);
String url = UrlBuilder.getIndividualProfileUrl(uri, vreq.getWebappDaoFactory()); String url = UrlBuilder.getIndividualProfileUrl(uri, vreq);
return (url == null) ? "" : url; // don't return a null to the template return (url == null) ? "" : url; // don't return a null to the template
} }

View file

@ -2,11 +2,14 @@
package edu.cornell.mannlib.vitro.webapp.web.templatemodels; package edu.cornell.mannlib.vitro.webapp.web.templatemodels;
import java.util.HashMap;
import javax.servlet.ServletContext; import javax.servlet.ServletContext;
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 edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder.ParamMap; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder.ParamMap;

View file

@ -2,6 +2,7 @@
package edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual; package edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual;
import java.util.HashMap;
import java.util.List; import java.util.List;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;

View file

@ -231,7 +231,7 @@ public class CollatedObjectPropertyTemplateModel extends ObjectPropertyTemplateM
} }
listForThisSubclass.add(new ObjectPropertyStatementTemplateModel(subjectUri, listForThisSubclass.add(new ObjectPropertyStatementTemplateModel(subjectUri,
propertyUri, objectKey, map, policyHelper, getTemplateName())); propertyUri, objectKey, map, policyHelper, getTemplateName(), vreq));
} }
return subclassMap; return subclassMap;

View file

@ -3,7 +3,7 @@
package edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual; package edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual;
import java.util.List; import java.util.List;
import java.util.HashMap;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
@ -30,12 +30,16 @@ public class DataPropertyStatementTemplateModel extends PropertyStatementTemplat
// Used for editing // Used for editing
private String dataPropHash = null; private String dataPropHash = null;
//Useful in case additional params to be retrieved for URL
private VitroRequest vitroRequest= null;
//Extended to include vitro request to check for special parameters
DataPropertyStatementTemplateModel(String subjectUri, String propertyUri, DataPropertyStatementTemplateModel(String subjectUri, String propertyUri,
Literal literal, EditingPolicyHelper policyHelper) { Literal literal, EditingPolicyHelper policyHelper, VitroRequest vreq) {
super(subjectUri, propertyUri, policyHelper); super(subjectUri, propertyUri, policyHelper);
this.value = literal.getLexicalForm(); this.value = literal.getLexicalForm();
this.vitroRequest = vreq;
setEditAccess(literal, policyHelper); setEditAccess(literal, policyHelper);
} }
@ -48,7 +52,7 @@ public class DataPropertyStatementTemplateModel extends PropertyStatementTemplat
*/ */
DataPropertyStatementTemplateModel(String subjectUri, String propertyUri, VitroRequest vreq, EditingPolicyHelper policyHelper) { DataPropertyStatementTemplateModel(String subjectUri, String propertyUri, VitroRequest vreq, EditingPolicyHelper policyHelper) {
super(subjectUri, propertyUri, policyHelper); super(subjectUri, propertyUri, policyHelper);
vitroRequest = vreq;
DataPropertyStatementDao dpsDao = vreq.getWebappDaoFactory().getDataPropertyStatementDao(); DataPropertyStatementDao dpsDao = vreq.getWebappDaoFactory().getDataPropertyStatementDao();
List<Literal> literals = dpsDao.getDataPropertyValuesForIndividualByProperty(subjectUri, propertyUri); List<Literal> literals = dpsDao.getDataPropertyValuesForIndividualByProperty(subjectUri, propertyUri);
@ -107,6 +111,12 @@ public class DataPropertyStatementTemplateModel extends PropertyStatementTemplat
if (! isDeletable()) { if (! isDeletable()) {
params.put("deleteProhibited", "prohibited"); params.put("deleteProhibited", "prohibited");
} }
//Check if special parameters being sent
HashMap<String, String> specialParams = UrlBuilder.getSpecialParams(vitroRequest);
if(specialParams.size() > 0) {
params.putAll(specialParams);
}
editUrl = UrlBuilder.getUrl(EDIT_PATH, params); editUrl = UrlBuilder.getUrl(EDIT_PATH, params);
} }
return editUrl; return editUrl;
@ -120,6 +130,11 @@ public class DataPropertyStatementTemplateModel extends PropertyStatementTemplat
"predicateUri", propertyUri, "predicateUri", propertyUri,
"datapropKey", dataPropHash, "datapropKey", dataPropHash,
"cmd", "delete"); "cmd", "delete");
//Check if special parameters being sent
HashMap<String, String> specialParams = UrlBuilder.getSpecialParams(vitroRequest);
if(specialParams.size() > 0) {
params.putAll(specialParams);
}
deleteUrl = UrlBuilder.getUrl(EDIT_PATH, params); deleteUrl = UrlBuilder.getUrl(EDIT_PATH, params);
} }
return deleteUrl; return deleteUrl;

View file

@ -3,6 +3,7 @@
package edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual; package edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
@ -30,11 +31,12 @@ public class DataPropertyTemplateModel extends PropertyTemplateModel {
private static final String EDIT_PATH = "edit/editDatapropStmtRequestDispatch.jsp"; private static final String EDIT_PATH = "edit/editDatapropStmtRequestDispatch.jsp";
private List<DataPropertyStatementTemplateModel> statements; private List<DataPropertyStatementTemplateModel> statements;
private VitroRequest vitroRequest = null;
DataPropertyTemplateModel(DataProperty dp, Individual subject, VitroRequest vreq, DataPropertyTemplateModel(DataProperty dp, Individual subject, VitroRequest vreq,
EditingPolicyHelper policyHelper, List<DataProperty> populatedDataPropertyList) { EditingPolicyHelper policyHelper, List<DataProperty> populatedDataPropertyList) {
super(dp, subject, policyHelper, vreq); super(dp, subject, policyHelper, vreq);
vitroRequest = vreq;
setName(dp.getPublicName()); setName(dp.getPublicName());
statements = new ArrayList<DataPropertyStatementTemplateModel>(); statements = new ArrayList<DataPropertyStatementTemplateModel>();
@ -45,7 +47,7 @@ public class DataPropertyTemplateModel extends PropertyTemplateModel {
DataPropertyStatementDao dpDao = vreq.getWebappDaoFactory().getDataPropertyStatementDao(); DataPropertyStatementDao dpDao = vreq.getWebappDaoFactory().getDataPropertyStatementDao();
List<Literal> values = dpDao.getDataPropertyValuesForIndividualByProperty(subject, dp); List<Literal> values = dpDao.getDataPropertyValuesForIndividualByProperty(subject, dp);
for (Literal value : values) { for (Literal value : values) {
statements.add(new DataPropertyStatementTemplateModel(subjectUri, propertyUri, value, policyHelper)); statements.add(new DataPropertyStatementTemplateModel(subjectUri, propertyUri, value, policyHelper, vreq));
} }
} else { } else {
log.debug("Data property " + getUri() + " is unpopulated."); log.debug("Data property " + getUri() + " is unpopulated.");
@ -88,6 +90,12 @@ public class DataPropertyTemplateModel extends PropertyTemplateModel {
ParamMap params = new ParamMap( ParamMap params = new ParamMap(
"subjectUri", subjectUri, "subjectUri", subjectUri,
"predicateUri", propertyUri); "predicateUri", propertyUri);
//Check if special parameters being sent
HashMap<String, String> specialParams = UrlBuilder.getSpecialParams(vitroRequest);
if(specialParams.size() > 0) {
params.putAll(specialParams);
}
addUrl = UrlBuilder.getUrl(EDIT_PATH, params); addUrl = UrlBuilder.getUrl(EDIT_PATH, params);
} }
return addUrl; return addUrl;

View file

@ -2,6 +2,7 @@
package edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual; package edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
@ -29,15 +30,16 @@ public class ObjectPropertyStatementTemplateModel extends PropertyStatementTempl
// Used for editing // Used for editing
private String objectUri = null; private String objectUri = null;
private String templateName = null; private String templateName = null;
private VitroRequest vitroRequest = null;
//Updating to include Vitro Request
ObjectPropertyStatementTemplateModel(String subjectUri, String propertyUri, String objectKey, ObjectPropertyStatementTemplateModel(String subjectUri, String propertyUri, String objectKey,
Map<String, String> data, EditingPolicyHelper policyHelper, String templateName) { Map<String, String> data, EditingPolicyHelper policyHelper, String templateName, VitroRequest vreq) {
super(subjectUri, propertyUri, policyHelper); super(subjectUri, propertyUri, policyHelper);
this.data = data; this.data = data;
this.objectUri = data.get(objectKey); this.objectUri = data.get(objectKey);
this.templateName = templateName; this.templateName = templateName;
this.vitroRequest = vreq;
setEditAccess(policyHelper); setEditAccess(policyHelper);
} }
@ -51,6 +53,7 @@ public class ObjectPropertyStatementTemplateModel extends PropertyStatementTempl
ObjectPropertyStatementTemplateModel(String subjectUri, String propertyUri, ObjectPropertyStatementTemplateModel(String subjectUri, String propertyUri,
VitroRequest vreq, EditingPolicyHelper policyHelper) { VitroRequest vreq, EditingPolicyHelper policyHelper) {
super(subjectUri, propertyUri, policyHelper); super(subjectUri, propertyUri, policyHelper);
vitroRequest = vreq;
} }
private void setEditAccess(EditingPolicyHelper policyHelper) { private void setEditAccess(EditingPolicyHelper policyHelper) {
@ -93,6 +96,11 @@ public class ObjectPropertyStatementTemplateModel extends PropertyStatementTempl
if (! isDeletable()) { if (! isDeletable()) {
params.put("deleteProhibited", "prohibited"); params.put("deleteProhibited", "prohibited");
} }
//Check if special parameters being sent
HashMap<String, String> specialParams = UrlBuilder.getSpecialParams(vitroRequest);
if(specialParams.size() > 0) {
params.putAll(specialParams);
}
editUrl = UrlBuilder.getUrl(EDIT_PATH, params); editUrl = UrlBuilder.getUrl(EDIT_PATH, params);
} }
@ -122,7 +130,11 @@ public class ObjectPropertyStatementTemplateModel extends PropertyStatementTempl
} }
} }
params.put("templateName", templateName); params.put("templateName", templateName);
//Check if special parameters being sent
HashMap<String, String> specialParams = UrlBuilder.getSpecialParams(vitroRequest);
if(specialParams.size() > 0) {
params.putAll(specialParams);
}
deleteUrl = UrlBuilder.getUrl(EDIT_PATH, params); deleteUrl = UrlBuilder.getUrl(EDIT_PATH, params);
} }

View file

@ -6,6 +6,7 @@ import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
@ -91,12 +92,14 @@ public abstract class ObjectPropertyTemplateModel extends PropertyTemplateModel
// Used for editing // Used for editing
private boolean addAccess = false; private boolean addAccess = false;
//To allow for checking of special parameters
private VitroRequest vitroRequest = null;
ObjectPropertyTemplateModel(ObjectProperty op, Individual subject, VitroRequest vreq, ObjectPropertyTemplateModel(ObjectProperty op, Individual subject, VitroRequest vreq,
EditingPolicyHelper policyHelper) EditingPolicyHelper policyHelper)
throws InvalidConfigurationException { throws InvalidConfigurationException {
super(op, subject, policyHelper, vreq); super(op, subject, policyHelper, vreq);
this.vitroRequest = vreq;
setName(op.getDomainPublic()); setName(op.getDomainPublic());
// Get the config for this object property // Get the config for this object property
@ -576,6 +579,12 @@ public abstract class ObjectPropertyTemplateModel extends PropertyTemplateModel
ParamMap params = new ParamMap( ParamMap params = new ParamMap(
"subjectUri", subjectUri, "subjectUri", subjectUri,
"predicateUri", propertyUri); "predicateUri", propertyUri);
//Check if special parameters being sent
HashMap<String, String> specialParams = UrlBuilder.getSpecialParams(vitroRequest);
if(specialParams.size() > 0) {
params.putAll(specialParams);
}
addUrl = UrlBuilder.getUrl(EDIT_PATH, params); addUrl = UrlBuilder.getUrl(EDIT_PATH, params);
} }

View file

@ -3,6 +3,7 @@
package edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual; package edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
@ -71,4 +72,5 @@ public class PropertyGroupTemplateModel extends BaseTemplateModel {
return properties; return properties;
} }
} }

View file

@ -3,11 +3,13 @@
package edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual; package edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
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 edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.web.templatemodels.BaseTemplateModel; import edu.cornell.mannlib.vitro.webapp.web.templatemodels.BaseTemplateModel;
public abstract class PropertyStatementTemplateModel extends BaseTemplateModel { public abstract class PropertyStatementTemplateModel extends BaseTemplateModel {
@ -49,4 +51,5 @@ public abstract class PropertyStatementTemplateModel extends BaseTemplateModel {
protected boolean isDeletable() { protected boolean isDeletable() {
return editAccessList.contains(EditAccess.DELETE); return editAccessList.contains(EditAccess.DELETE);
} }
} }

View file

@ -42,7 +42,7 @@ public class UncollatedObjectPropertyTemplateModel extends ObjectPropertyTemplat
String objectKey = getObjectKey(); String objectKey = getObjectKey();
for (Map<String, String> map : statementData) { for (Map<String, String> map : statementData) {
statements.add(new ObjectPropertyStatementTemplateModel(subjectUri, statements.add(new ObjectPropertyStatementTemplateModel(subjectUri,
propertyUri, objectKey, map, policyHelper, getTemplateName())); propertyUri, objectKey, map, policyHelper, getTemplateName(), vreq));
} }
postprocessStatementList(statements); postprocessStatementList(statements);

View file

@ -1,7 +1,7 @@
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ --> <#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
<#-- Default individual profile page template --> <#-- Default individual profile page template -->
<#--@dumpAll /-->
<section id="individual-intro" class="vcard" role="region"> <section id="individual-intro" class="vcard" role="region">
<#-- Image --> <#-- Image -->
<#assign individualImage> <#assign individualImage>

View file

@ -0,0 +1,61 @@
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
<#-- List individuals in the requested class. -->
<#import "lib-list.ftl" as l>
<section id="menupage-intro" role="region">
<h2>${page.title}</h2>
</section>
${stylesheets.add('<link rel="stylesheet" href="${urls.base}/css/browseIndex.css" />')}
<#assign pageurl = page.urlMapping>
<section class="individualList">
<#if message??>
<p>${message}</p>
<#else>
<#assign pagination>
<#if (pages?size > 1) >
pages:
<ul class="pagination">
<#list pages as page>
<#if page.selected>
<li class="selectedNavPage">${page.text}</li>
<#else>
<#-- RY Ideally the urls would be generated by the controller; see search-pagedResults.ftl -->
<li><a href="${urls.base}${pageurl}?${page.param}">${page.text}</a></li>
</#if>
</#list>
</ul>
</#if>
</#assign>
${pagination}
<ul>
<#list individuals as individual>
<li>
<#assign moniker = individual.moniker!>
<a href="${individual.profileUrl}">${individual.name}</a><#if moniker?has_content> <span class="moniker">${moniker}</span></#if>
<#assign links = individual.links>
<#if links?has_content>
<ul class="individualData">
<@l.firstLastList>
<#list links as link>
<li><a class="externalLink" href="${link.url}">${link.anchor}</a></li>
</#list>
</@l.firstLastList>
</ul>
</#if>
</li>
</#list>
</ul>
${pagination}
</#if>
</section> <!-- .individualList -->

View file

@ -33,6 +33,7 @@
</#list> </#list>
</#macro> </#macro>
<#macro objectProperty property editable template=property.template> <#macro objectProperty property editable template=property.template>
<#if property.collatedBySubclass> <#-- collated --> <#if property.collatedBySubclass> <#-- collated -->
<@collatedObjectPropertyList property editable template /> <@collatedObjectPropertyList property editable template />
@ -44,6 +45,7 @@
</#if> </#if>
</#macro> </#macro>
<#macro collatedObjectPropertyList property editable template=property.template > <#macro collatedObjectPropertyList property editable template=property.template >
<#assign subclasses = property.subclasses> <#assign subclasses = property.subclasses>
<#list subclasses?keys as subclass> <#list subclasses?keys as subclass>
@ -90,6 +92,7 @@ name will be used as the label. -->
<#macro addLink property editable label="${property.name}" extraParams=""> <#macro addLink property editable label="${property.name}" extraParams="">
<#if editable> <#if editable>
<#--@dump var="property"/-->
<#local url = property.addUrl> <#local url = property.addUrl>
<#if url?has_content> <#if url?has_content>
<@showAddLink property.localName label addParamsToEditUrl(url, extraParams) /> <@showAddLink property.localName label addParamsToEditUrl(url, extraParams) />
@ -114,6 +117,7 @@ name will be used as the label. -->
<h2 id="${property.localName}">${label} <@verboseDisplay property /></h2> <h2 id="${property.localName}">${label} <@verboseDisplay property /></h2>
</#macro> </#macro>
<#macro propertyListItem property statement editable > <#macro propertyListItem property statement editable >
<li role="listitem"> <li role="listitem">
<#nested> <#nested>
@ -217,7 +221,7 @@ name will be used as the label. -->
<#-- Don't assume that if the mainImage property is populated, there is a thumbnail image (though that is the general case). <#-- Don't assume that if the mainImage property is populated, there is a thumbnail image (though that is the general case).
If there's a mainImage statement but no thumbnail image, treat it as if there is no image. --> If there's a mainImage statement but no thumbnail image, treat it as if there is no image. -->
<#if (mainImage.statements)?has_content && thumbUrl?has_content> <#if (mainImage.statements)?has_content && thumbUrl?has_content>
<a href="${individual.imageUrl}"><img class="individual-photo" src="${thumbUrl}" title="click to view larger image" alt="${individual.name}" width="160" /></a> <a href="${individual.imageUrl}"><img class="individual-photo" src="${tlhumbUrl}" title="click to view larger image" alt="${individual.name}" width="160" /></a>
<@editingLinks "${mainImage.localName}" mainImage.first editable extraParams /> <@editingLinks "${mainImage.localName}" mainImage.first editable extraParams />
<#else> <#else>
<#local imageLabel><@addLinkWithLabel mainImage editable "Photo" extraParams /></#local> <#local imageLabel><@addLinkWithLabel mainImage editable "Photo" extraParams /></#local>
@ -236,3 +240,5 @@ name will be used as the label. -->
${label.value} ${label.value}
<@editingLinks "label" label editable /> <@editingLinks "label" label editable />
</#macro> </#macro>