Changes to fix error with NIHVIVO-2726 (switching to main model removes original model). Also updated template for individuals for classes to employ main class group template. Also fixed error NIHVIVO-2785 where clicking on class on internal/external page repeated class name on page.

This commit is contained in:
hjkhjk54 2011-06-28 19:54:23 +00:00
parent 997b3ef2cd
commit 030b454a2b
12 changed files with 166 additions and 166 deletions

View file

@ -58,9 +58,6 @@ public class PageController extends FreemarkerHttpServlet{
mapForTemplate.put("title", page.get("title"));
}
//For multiple classes,
//mapForTemplate.put("dataServiceUrlIndividualsByVClasses", UrlBuilder.getUrl("/dataservice?getSolrIndividualsByVClasses=1&vclassId="));
} catch (Throwable th) {
return doNotFound(vreq);
}

View file

@ -19,6 +19,7 @@ import edu.cornell.mannlib.vitro.webapp.beans.ApplicationBean;
import edu.cornell.mannlib.vitro.webapp.beans.Individual;
import edu.cornell.mannlib.vitro.webapp.beans.IndividualImpl;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.dao.DisplayVocabulary;
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
public class UrlBuilder {
@ -372,21 +373,21 @@ public class UrlBuilder {
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");
String useMenuModelParam = vreq.getParameter(DisplayVocabulary.SWITCH_TO_DISPLAY_MODEL);
//the parameters below allow for using a different model
String useMainModelUri = vreq.getParameter("usemodel");
String useTboxModelUri = vreq.getParameter("usetboxmodel");
String useDisplayModelUri = vreq.getParameter("usedisplaymodel");
String useMainModelUri = vreq.getParameter(DisplayVocabulary.USE_MODEL_PARAM);
String useTboxModelUri = vreq.getParameter(DisplayVocabulary.USE_TBOX_MODEL_PARAM);
String useDisplayModelUri = vreq.getParameter(DisplayVocabulary.USE_DISPLAY_MODEL_PARAM);
if(useMenuModelParam != null && !useMenuModelParam.isEmpty()) {
specialParams.put("usemenumodel", useMenuModelParam);
specialParams.put(DisplayVocabulary.SWITCH_TO_DISPLAY_MODEL, useMenuModelParam);
}
else if(useMainModelUri != null && !useMainModelUri.isEmpty()) {
specialParams.put("usemodel", useMainModelUri);
specialParams.put(DisplayVocabulary.USE_MODEL_PARAM, useMainModelUri);
if(useTboxModelUri != null && !useTboxModelUri.isEmpty()){
specialParams.put("usetboxmodel", useTboxModelUri);
specialParams.put(DisplayVocabulary.USE_TBOX_MODEL_PARAM, useTboxModelUri);
}
if(useDisplayModelUri != null && !useDisplayModelUri.isEmpty()) {
specialParams.put("usedisplaymodel", useDisplayModelUri);
specialParams.put(DisplayVocabulary.USE_DISPLAY_MODEL_PARAM, useDisplayModelUri);
}
}
}

View file

@ -97,6 +97,16 @@ public class DisplayVocabulary {
/** <p>Class of pages.</p> */
public static final OntClass PAGE = m_model.createClass( NS + "Page" );
//Parameters to switch to menu editing - or to switch models
public static final String SWITCH_TO_DISPLAY_MODEL = "switchToDisplayModel";
public static final String USE_MODEL_PARAM = "useThisModel";
public static final String USE_TBOX_MODEL_PARAM = "useThisTboxModel";
public static final String USE_DISPLAY_MODEL_PARAM = "useThisDisplayModel";
//Attribute values used to store display tbox/display display model in servlet context
public static final String CONTEXT_DISPLAY_TBOX = "displayOntModelTBOX";
public static final String CONTEXT_DISPLAY_DISPLAY = "displayOntModelDisplayModel";
/* URIs for some individuals in the dispaly ontology */

View file

@ -623,18 +623,72 @@ public class WebappDaoFactoryJena implements WebappDaoFactory {
}
}
//Method for creating a copy - does not pass the same object
public WebappDaoFactoryJena (WebappDaoFactoryJena base) {
//Not sure if selector somehow has greater longevity so making a copy instead of reference
if(base.ontModelSelector instanceof OntModelSelectorImpl) {
OntModelSelectorImpl selector = new OntModelSelectorImpl();
selector.setABoxModel(base.ontModelSelector.getABoxModel());
selector.setApplicationMetadataModel(base.ontModelSelector.getApplicationMetadataModel());
selector.setDisplayModel(base.ontModelSelector.getDisplayModel());
selector.setFullModel(base.ontModelSelector.getFullModel());
selector.setTBoxModel(base.ontModelSelector.getTBoxModel());
selector.setUserAccountsModel(base.ontModelSelector.getUserAccountsModel());
this.ontModelSelector = selector;
} else if(base.ontModelSelector instanceof SimpleOntModelSelector) {
SimpleOntModelSelector selector = new SimpleOntModelSelector();
selector.setABoxModel(base.ontModelSelector.getABoxModel());
selector.setApplicationMetadataModel(base.ontModelSelector.getApplicationMetadataModel());
selector.setDisplayModel(base.ontModelSelector.getDisplayModel());
selector.setFullModel(base.ontModelSelector.getFullModel());
selector.setTBoxModel(base.ontModelSelector.getTBoxModel());
selector.setUserAccountsModel(base.ontModelSelector.getUserAccountsModel());
this.ontModelSelector = selector;
} else {
//Not sure what this is but will set to equivalence here
this.ontModelSelector =base.ontModelSelector;
}
this.defaultNamespace = base.defaultNamespace;
this.nonuserNamespaces = base.nonuserNamespaces;
this.preferredLanguages = base.preferredLanguages;
this.userURI = base.userURI;
this.flag2ValueMap = new HashMap<String,OntClass>();
this.flag2ValueMap.putAll(base.flag2ValueMap);
this.flag2ClassLabelMap = new HashMap<Resource, String>();
this.flag2ClassLabelMap.putAll(base.flag2ClassLabelMap);
this.dwf = base.dwf;
}
//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
public boolean isUsingSpecialModel = false;
public void setSpecialDataModel(OntModel specialModel, OntModel specialTboxModel, OntModel specialDisplayModel) {
//Can we get the "original" models here from somewhere?
OntModelSelector originalSelector = this.getOntModelSelector();
//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);
if(specialDisplayModel != null) {
specialSelector.setDisplayModel(specialDisplayModel);
} else {
OntModel selectorDisplayModel = originalSelector.getDisplayModel();
if(selectorDisplayModel != null) {
specialSelector.setDisplayModel(originalSelector.getDisplayModel());
}
}
if(specialTboxModel != null) {
specialSelector.setTBoxModel(specialTboxModel);
} else {
OntModel selectorTboxModel = originalSelector.getTBoxModel();
if(selectorTboxModel != null) {
specialSelector.setTBoxModel(originalSelector.getTBoxModel());
}
}
specialSelector.setABoxModel(specialModel);
specialSelector.setUserAccountsModel(specialModel);
//although we're only use part of the new wadf and copy over below, the object property dao
@ -642,7 +696,6 @@ public class WebappDaoFactoryJena implements WebappDaoFactory {
//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();
keys2EntsDao = specialWadfj.getKeys2EntsDao();
keywordDao = specialWadfj.getKeywordDao();
@ -657,23 +710,8 @@ public class WebappDaoFactoryJena implements WebappDaoFactory {
objectPropertyStatementDao = specialWadfj.getObjectPropertyStatementDao();
dataPropertyDao = specialWadfj.getDataPropertyDao();
dataPropertyStatementDao = specialWadfj.getDataPropertyStatementDao();
PropertyGroup pgtest = new edu.cornell.mannlib.vitro.webapp.beans.PropertyGroup();
pgtest.setName("testname");
pgtest.setDisplayRank(1);
propertyGroupDao.insertNewPropertyGroup(pgtest);
//?Simple ont model selector uses submodels - unsure if relevant here
//|| ontModelSelector instanceof SimpleOntModelSelector
if(ontModelSelector instanceof OntModelSelectorImpl) {
OntModelSelectorImpl omsImpl = (OntModelSelectorImpl) ontModelSelector;
omsImpl.setTBoxModel(specialTboxModel);
omsImpl.setDisplayModel(specialDisplayModel);
}
else if(ontModelSelector instanceof SimpleOntModelSelector) {
SimpleOntModelSelector omsImpl = (SimpleOntModelSelector) ontModelSelector;
omsImpl.setTBoxModel(specialTboxModel);
omsImpl.setDisplayModel(specialDisplayModel);
}
isUsingSpecialModel = true;
//Why can't we set the selector to be the same?
ontModelSelector = specialSelector;
}
}

View file

@ -5,7 +5,8 @@ package edu.cornell.mannlib.vitro.webapp.filters;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.Map;
import java.util.Set;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
@ -129,8 +130,8 @@ public class VitroRequestPrep implements Filter {
wdf = (WebappDaoFactory) o;
log.debug("Found a WebappDaoFactory in the session and using it for this request");
}
checkForSpecialWDF(vreq, wdf);
//This will replace the WebappDaoFactory with a different version if menu management parameter is found
wdf = checkForSpecialWDF(vreq, wdf);
VitroFilters filters = null;
@ -203,53 +204,75 @@ public class VitroRequestPrep implements Filter {
//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) {
String useMenuModelParam = vreq.getParameter("usemenumodel");
private WebappDaoFactory checkForSpecialWDF(VitroRequest vreq, WebappDaoFactory inputWadf) {
String useMenuModelParam = vreq.getParameter(DisplayVocabulary.SWITCH_TO_DISPLAY_MODEL);
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");
String useMainModelUri = vreq.getParameter(DisplayVocabulary.USE_MODEL_PARAM);
String useTboxModelUri = vreq.getParameter(DisplayVocabulary.USE_TBOX_MODEL_PARAM);
String useDisplayModelUri = vreq.getParameter(DisplayVocabulary.USE_DISPLAY_MODEL_PARAM);
if(useMenu || (useMainModelUri != null && !useMainModelUri.isEmpty() && useTboxModelUri != null && !useTboxModelUri.isEmpty())) {
if(wadf instanceof WebappDaoFactoryJena) {
WebappDaoFactoryJena wadfj = (WebappDaoFactoryJena) wadf;
log.debug("Menu switching parameters exist, Use Menu: " + useMenu + " - UseModelUri:" + useMainModelUri + " - UseTboxModelUri:" + useTboxModelUri + " - useDisplayModelUri:" + useDisplayModelUri);
if(inputWadf instanceof WebappDaoFactoryJena) {
//Create a copy of the input WADF to be sent over and then set
WebappDaoFactoryJena wadfj = new WebappDaoFactoryJena((WebappDaoFactoryJena) inputWadf);
log.debug("Created copy of input webapp dao factory to be overwritten");
//WebappDaoFactoryJena wadfj = (WebappDaoFactoryJena) wadf;
OntModel useMainOntModel = null, useTboxOntModel = null, useDisplayOntModel = null;
Model tboxModel = null, displayModel = null;
BasicDataSource bds = JenaDataSourceSetupBase.getApplicationDataSource(_context);
String dbType = ConfigurationProperties.getBean(_context).getProperty( // database type
"VitroConnection.DataSource.dbtype", "MySQL");
if(useMenu) {
log.debug("Display model editing mode");
//if using special models for menu management, get main menu model from context and set tbox and display uris to be used
useMainOntModel = (OntModel) _context.getAttribute("displayOntModel");
//Hardcoding tbox model uri for now
useTboxModelUri = DisplayVocabulary.DISPLAY_TBOX_MODEL_URI;
useDisplayModelUri = DisplayVocabulary.DISPLAY_DISPLAY_MODEL_URI;
//Get tbox and display display model from servlet context otherwise load in directly from database
useTboxOntModel = (OntModel) _context.getAttribute(DisplayVocabulary.CONTEXT_DISPLAY_TBOX);
useDisplayOntModel = (OntModel) _context.getAttribute(DisplayVocabulary.CONTEXT_DISPLAY_DISPLAY);
} else {
log.debug("Display model editing mode not triggered, using model uri " + useMainModelUri);
//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) {
log.debug("main model uri exists");
useMainOntModel = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM, mainModel);
} else {
log.error("Main Model Uri " + useMainModelUri + " did not retrieve model");
}
}
//Get tbox and display display model from servlet context otherwise load in directly from database
useTboxOntModel = (OntModel) _context.getAttribute("displayOntModelTBOX");
useDisplayOntModel = (OntModel) _context.getAttribute("displayOntModelDisplayModel");
if(useTboxOntModel == null){
if(!useMenu || useTboxOntModel == null){
tboxModel = JenaDataSourceSetupBase.makeDBModel(bds, useTboxModelUri, OntModelSpec.OWL_MEM, JenaDataSourceSetupBase.TripleStoreType.RDB, dbType, _context);
useTboxOntModel = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM, tboxModel);
}
if(useDisplayOntModel == null) {
if(!useMenu || useDisplayOntModel == null) {
//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) {
log.debug("Switching to use of input model");
//If menu model, preserve existing display model so the navigation elements remain
if(useMenu) {
useDisplayOntModel = null;
}
//Changes will be made to the copy, not the original from the servlet context
wadfj.setSpecialDataModel(useMainOntModel, useTboxOntModel, useDisplayOntModel);
return wadfj;
}
}
}
//if no parameters exist for switching models, return the original webapp dao factory object
return inputWadf;
}
}

View file

@ -3,6 +3,7 @@
package edu.cornell.mannlib.vitro.webapp.servlet.setup;
import java.io.InputStream;
import java.io.File;
import java.sql.SQLException;
import java.util.Set;
@ -335,6 +336,9 @@ public class JenaDataSourceSetupBase extends JenaBaseDaoCon {
}
public static void readOntologyFileFromPath(String p, Model model, ServletContext ctx) {
//Check that this is a file and not a directory
File f = new File(ctx.getRealPath(p));
if(f.exists() && f.isFile()){
String format = getRdfFormat(p);
log.info("Loading ontology file at " + p +
" as format " + format);
@ -346,6 +350,14 @@ public class JenaDataSourceSetupBase extends JenaBaseDaoCon {
log.error("Failed to load ontology file at '" + p +
"' as format " + format, t);
}
} else {
if(!f.exists()) {
log.debug("File for path " + p + " does not exist");
}
else if(f.isDirectory()) {
log.debug("Path " + p + " corresponds to directory and not file so was not read in");
}
}
}
private static String getRdfFormat(String filename){

View file

@ -56,14 +56,18 @@ public class JenaPersistentDataSourceSetup extends JenaDataSourceSetupBase
try {
Model appDbModel = makeDBModelFromConfigurationProperties(
JENA_DISPLAY_METADATA_MODEL, DB_ONT_MODEL_SPEC, ctx);
if (appDbModel.size() == 0)
log.debug("Display model size is " + appDbModel.size());
if (appDbModel.size() == 0) {
readOntologyFilesInPathSet(
APPPATH, sce.getServletContext(),appDbModel);
log.debug("Loaded ontology files from " + APPPATH + " into display model");
}
OntModel appModel = ModelFactory.createOntologyModel(
MEM_ONT_MODEL_SPEC);
appModel.add(appDbModel);
appModel.getBaseModel().register(new ModelSynchronizer(appDbModel));
ctx.setAttribute("displayOntModel", appModel);
} catch (Throwable t) {
log.error("Unable to load user application configuration model from DB", t);
}
@ -80,6 +84,7 @@ public class JenaPersistentDataSourceSetup extends JenaDataSourceSetupBase
appTBOXModel.add(displayTboxModel);
appTBOXModel.getBaseModel().register(new ModelSynchronizer(displayTboxModel));
ctx.setAttribute("displayOntModelTBOX", appTBOXModel);
log.debug("Loaded file " + APPPATH_LOAD + "displayTBOX.n3 into display tbox model");
} catch (Throwable t) {
log.error("Unable to load user application configuration model TBOX from DB", t);
}
@ -96,6 +101,7 @@ public class JenaPersistentDataSourceSetup extends JenaDataSourceSetupBase
appDisplayDisplayModel.add(displayDisplayModel);
appDisplayDisplayModel.getBaseModel().register(new ModelSynchronizer(displayDisplayModel));
ctx.setAttribute("displayOntModelDisplayModel", appDisplayDisplayModel);
log.debug("Loaded file " + APPPATH_LOAD + "displayDisplay.n3 into display display model");
} catch (Throwable t) {
log.error("Unable to load user application configuration model Display Model from DB", t);
}

View file

@ -124,8 +124,9 @@ public class ClassGroupPageData implements PageDataGetter{
/**
* For processig of JSONObject
* For processing of JSONObject
*/
//Currently empty, TODO: Review requirements
public JSONObject convertToJSON(Map<String, Object> dataMap, VitroRequest vreq) {
JSONObject rObj = null;
return rObj;

View file

@ -74,17 +74,17 @@ public class IndividualsForClassesDataGetter implements PageDataGetter{
VClass vclass = vcgc.getCachedVClass(classUri);
if(vclass != null) {
System.out.println("VClass does exist for " + classUri + " and entity count is " + vclass.getEntityCount());
log.debug("VClass does exist for " + classUri + " and entity count is " + vclass.getEntityCount());
vClasses.add(vclass);
} else {
System.out.println("Vclass " + classUri + " does not exist in the cache");
log.debug("Vclass " + classUri + " does not exist in the cache");
log.error("Error occurred, vclass does not exist for this uri " + classUri);
//Throw exception here
}
}
classesGroup.setVitroClassList(vClasses);
//What is individual count? Total?
classesGroup.setIndividualCount(vClasses.size());
//classesGroup.setIndividualCount(vClasses.size());
data.put("vClassGroup", classesGroup);
List<String> urlEncodedRestrictClasses = new ArrayList<String>();
if(restrictClasses.size() > 0) {
@ -100,17 +100,6 @@ public class IndividualsForClassesDataGetter implements PageDataGetter{
urlEncodedRestrictClasses.add(URLEncoder.encode(restrictClassUri, "UTF-8"));
}
/*
//If we were actually getting the intersections
for(String classUri: classes) {
List<String> intersectionUris = new ArrayList<String>();
intersectionUris.add(classUri);
intersectionUris.addAll(restrictClasses);
Map<String, Object> results = SolrIndividualListController.getResultsForVClassIntersections(intersectionUris, pageParam, alpha, vreq.getWebappDaoFactory().getIndividualDao(), context);
data.putAll(results);
List<Individual> entities = (List<Individual>)results.get("entities");
inds.addAll(entities);
}*/
restrictClassesGroup.setVitroClassList(restrictVClasses);
restrictClassesGroup.setIndividualCount(restrictVClasses.size());
} else {
@ -124,31 +113,6 @@ public class IndividualsForClassesDataGetter implements PageDataGetter{
data.put("restrictVClasses", restrictVClasses);
//not sure if this is useful
data.put("restrictVClassGroup", restrictClassesGroup);
//if we were returning actual results
/*
//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<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/");
*/
//Also add data service url
//Hardcoding for now, need a more dynamic way of doing this
data.put("dataServiceUrlIndividualsByVClass", this.getDataServiceUrl());

View file

@ -104,13 +104,12 @@ browseByVClass.getIndividuals = function(vclassUri, alpha, page, scroll) {
pages = results.pages;
browseByVClass.pagination(pages, page);
}
//Check if single vclass sent back, otherwise check for vclasses
if(results.vclass) {
selectedClassHeading = '<h3 class="selected-class">'+ results.vclass.name +'</h3>';
browseByVClass.individualsContainer.prepend(selectedClassHeading);
}
$('h3.selected-class').text(results.vclass.name);
// set selected class, alpha and page
browseByVClass.selectedVClass(results.vclass.URI);
}
browseByVClass.selectedAlpha(alpha);
}
});

View file

@ -1,19 +1,9 @@
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
<#include "menupage-checkForData.ftl">
<#--Not including data check because vclasses don't appear to return entity counts on their own -->
<#--Need to add restrict classes information-->
<input type="hidden" name="restrictClasses" id="restrictClasses" value="${restrictClasses}"/>
<#--Using the same page setup as regular class groups so including the entire template-->
<#include "menupage.ftl">
<#--add script-->
<#if !noData>
<section id="menupage-intro" class="people" role="region">
<h2>${page.title}</h2>
</section>
<#include "menupage-individualsforclasses-browse.ftl">
${stylesheets.add('<link rel="stylesheet" href="${urls.base}/css/menupage/menupage.css" />')}
<#include "menupage-scripts.ftl">
${scripts.add('<script type="text/javascript" src="${urls.base}/js/menupage/browseByVClasses.js"></script>')}
<#else>
<# ${noDataNotification} >
</#if>

View file

@ -1,41 +0,0 @@
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
<#-- Template for browsing individuals in class groups for menupages -->
<#import "lib-string.ftl" as str>
<section id="browse-by" role="region">
<nav role="navigation">
<ul id="browse-classes">
<#list vClassGroup as vClass>
<#------------------------------------------------------------
Need to replace vClassCamel with full URL that allows function
to degrade gracefully in absence of JavaScript. Something
similar to what Brian had setup with widget-browse.ftl
------------------------------------------------------------->
<#assign vClassCamel = str.camelCase(vClass.name) />
<#-- Only display vClasses with individuals -->
<#if (vClass.entityCount > 0)>
<li id="${vClassCamel}"><a href="#${vClassCamel}" title="Browse all individuals in this class" data-uri="${vClass.URI}">${vClass.name} <span class="count-classes">(${vClass.entityCount})</span></a></li>
</#if>
</#list>
<#--Including restriction classes as hidden input, for now using just string uri---->
<input type="hidden" name="restrictClasses" id="restrictClasses" value="${restrictClasses}"/>
</ul>
<nav role="navigation">
<#assign alphabet = ["A", "B", "C", "D", "E", "F", "G" "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"] />
<ul id="alpha-browse-individuals">
<li><a href="#" class="selected" data-alpha="all">All</a></li>
<#list alphabet as letter>
<li><a href="#" data-alpha="${letter?lower_case}" title="Browse all individuals whose name starts with ${letter}">${letter}</a></li>
</#list>
</ul>
</nav>
</nav>
<section id="individuals-in-class" role="region">
<ul role="list">
<#-- Will be populated dynamically via AJAX request -->
</ul>
</section>
</section>