NIHVIVO-1341 Implement preprocessing structure to process object property statement query data before sending to template. Reorganize markup in templates to reduce repetition.

This commit is contained in:
rjy7 2010-12-16 14:57:04 +00:00
parent dbb07aa152
commit b6b3499922
19 changed files with 241 additions and 169 deletions

View file

@ -244,9 +244,18 @@ public class UrlBuilder {
return getPath(route.path(), params); return getPath(route.path(), params);
} }
public static String getIndividualProfileUrl(String individualUri, WebappDaoFactory wadf) {
Individual individual = wadf.getIndividualDao().getIndividualByURI(individualUri);
return getIndividualProfileUrl(individual, individualUri, wadf);
}
public static String getIndividualProfileUrl(Individual individual, WebappDaoFactory wadf) { public static String getIndividualProfileUrl(Individual individual, WebappDaoFactory wadf) {
String profileUrl = null;
String individualUri = individual.getURI(); String individualUri = individual.getURI();
return getIndividualProfileUrl(individual, individualUri, wadf);
}
private static String getIndividualProfileUrl(Individual individual, String individualUri, WebappDaoFactory wadf) {
String profileUrl = null;
URI uri = new URIImpl(individualUri); URI uri = new URIImpl(individualUri);
String namespace = uri.getNamespace(); String namespace = uri.getNamespace();
String defaultNamespace = wadf.getDefaultNamespace(); String defaultNamespace = wadf.getDefaultNamespace();

View file

@ -30,5 +30,5 @@ public interface ObjectPropertyStatementDao {
int insertNewObjectPropertyStatement(ObjectPropertyStatement objPropertyStmt ); int insertNewObjectPropertyStatement(ObjectPropertyStatement objPropertyStmt );
public List<Map<String, Object>> getObjectPropertyStatementsForIndividualByProperty(String subjectUri, String propertyUri, String query); public List<Map<String, String>> getObjectPropertyStatementsForIndividualByProperty(String subjectUri, String propertyUri, String query);
} }

View file

@ -84,7 +84,7 @@ class ObjectPropertyStatementDaoFiltering extends BaseFiltering implements Objec
@Override @Override
// RY What about filtering? // RY What about filtering?
public List<Map<String, Object>> getObjectPropertyStatementsForIndividualByProperty( public List<Map<String, String>> getObjectPropertyStatementsForIndividualByProperty(
String subjectUri, String propertyUri, String query) { String subjectUri, String propertyUri, String query) {
return innerObjectPropertyStatementDao.getObjectPropertyStatementsForIndividualByProperty(subjectUri, propertyUri, query); return innerObjectPropertyStatementDao.getObjectPropertyStatementsForIndividualByProperty(subjectUri, propertyUri, query);
} }

View file

@ -898,9 +898,7 @@ public class ObjectPropertyDaoJena extends PropertyDaoJena implements ObjectProp
ResultSet results = qexec.execSelect(); ResultSet results = qexec.execSelect();
while (results.hasNext()) { while (results.hasNext()) {
QuerySolution soln = results.next(); QuerySolution soln = results.next();
Resource resource = soln.getResource("property"); ObjectProperty prop = getObjectPropertyByURI(soln.getResource("property").getURI());
String uri = resource.getURI();
ObjectProperty prop = getObjectPropertyByURI(uri);
String filename = soln.getLiteral("filename").getLexicalForm(); String filename = soln.getLiteral("filename").getLexicalForm();
customListViewConfigFileMap.put(prop, filename); customListViewConfigFileMap.put(prop, filename);
} }

View file

@ -251,7 +251,7 @@ public class ObjectPropertyStatementDaoJena extends JenaBaseDao implements Objec
* custom queries that could request any data in addition to just the object of the statement. * custom queries that could request any data in addition to just the object of the statement.
* However, we do need to get the object of the statement so that we have it to create editing links. * However, we do need to get the object of the statement so that we have it to create editing links.
*/ */
public List<Map<String, Object>> getObjectPropertyStatementsForIndividualByProperty(String subjectUri, String propertyUri, String queryString) { public List<Map<String, String>> getObjectPropertyStatementsForIndividualByProperty(String subjectUri, String propertyUri, String queryString) {
log.debug("Object property query string: " + queryString); log.debug("Object property query string: " + queryString);
@ -269,47 +269,16 @@ public class ObjectPropertyStatementDaoJena extends JenaBaseDao implements Objec
// Run the SPARQL query to get the properties // Run the SPARQL query to get the properties
QueryExecution qexec = QueryExecutionFactory.create(query, getOntModelSelector().getFullModel(), bindings); QueryExecution qexec = QueryExecutionFactory.create(query, getOntModelSelector().getFullModel(), bindings);
return executeQueryToObjectValueCollection(qexec);
}
protected List<Map<String, Object>> executeQueryToObjectValueCollection(
QueryExecution qexec) {
List<Map<String, Object>> rv = new ArrayList<Map<String, Object>>();
ResultSet results = qexec.execSelect(); ResultSet results = qexec.execSelect();
List<Map<String, String>> list = new ArrayList<Map<String, String>>();
while (results.hasNext()) { while (results.hasNext()) {
QuerySolution soln = results.nextSolution(); QuerySolution soln = results.nextSolution();
rv.add(querySolutionToObjectValueMap(soln)); list.add(QueryUtils.querySolutionToStringValueMap(soln));
} }
return rv; return list;
} }
protected Map<String,Object> querySolutionToObjectValueMap( QuerySolution soln){
Map<String,Object> map = new HashMap<String,Object>();
Iterator<String> varNames = soln.varNames();
while(varNames.hasNext()){
String varName = varNames.next();
map.put(varName, nodeToObject( soln.get(varName)));
}
return map;
}
protected Object nodeToObject( RDFNode node ){
if( node == null ){
return "";
}else if( node.isLiteral() ){
Literal literal = node.asLiteral();
//return literal.getValue();
return literal.getLexicalForm();
}else if( node.isURIResource() ){
Resource resource = node.asResource();
// See notes in ObjectPropertyStatementTemplateModel about why we are returning the individual
// here instead of just the URI.
return getWebappDaoFactory().getIndividualDao().getIndividualByURI(resource.getURI());
}else if( node.isAnon() ){
Resource resource = node.asResource();
return resource.getId().getLabelString(); //get b-node id
}else{
return "";
}
}
} }

View file

@ -0,0 +1,78 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.dao.jena;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import com.hp.hpl.jena.query.QueryExecution;
import com.hp.hpl.jena.query.QuerySolution;
import com.hp.hpl.jena.query.ResultSet;
import com.hp.hpl.jena.rdf.model.Literal;
import com.hp.hpl.jena.rdf.model.RDFNode;
import com.hp.hpl.jena.rdf.model.Resource;
/**
* Utilities for executing queries and working with query results.
*
*/
public class QueryUtils {
protected static Map<String,Object> querySolutionToObjectValueMap( QuerySolution soln){
Map<String,Object> map = new HashMap<String,Object>();
Iterator<String> varNames = soln.varNames();
while(varNames.hasNext()){
String varName = varNames.next();
map.put(varName, nodeToObject( soln.get(varName)));
}
return map;
}
protected static Map<String,String> querySolutionToStringValueMap( QuerySolution soln ){
Map<String,String> map = new HashMap<String,String>();
Iterator<String> varNames = soln.varNames();
while(varNames.hasNext()){
String varName = varNames.next();
map.put(varName, nodeToString( soln.get(varName)));
}
return map;
}
protected static Object nodeToObject( RDFNode node ){
if( node == null ){
return "";
}else if( node.isLiteral() ){
Literal literal = node.asLiteral();
return literal.getValue();
}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 "";
}
}
protected static 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 "";
}
}
}

View file

@ -22,7 +22,7 @@ public class CollatedObjectPropertyTemplateModel extends ObjectPropertyTemplateM
private static final Log log = LogFactory.getLog(CollatedObjectPropertyTemplateModel.class); private static final Log log = LogFactory.getLog(CollatedObjectPropertyTemplateModel.class);
private Map<String, List<ObjectPropertyStatementTemplateModel>> collatedStatements; private Map<String, List<ObjectPropertyStatementTemplateModel>> subclasses;
//private List<SubclassList> subclassList; //private List<SubclassList> subclassList;
CollatedObjectPropertyTemplateModel(ObjectProperty op, Individual subject, WebappDaoFactory wdf) throws Exception { CollatedObjectPropertyTemplateModel(ObjectProperty op, Individual subject, WebappDaoFactory wdf) throws Exception {
@ -53,16 +53,16 @@ public class CollatedObjectPropertyTemplateModel extends ObjectPropertyTemplateM
ObjectPropertyStatementDao opDao = wdf.getObjectPropertyStatementDao(); ObjectPropertyStatementDao opDao = wdf.getObjectPropertyStatementDao();
String subjectUri = subject.getURI(); String subjectUri = subject.getURI();
String propertyUri = op.getURI(); String propertyUri = op.getURI();
List<Map<String, Object>> statementData = opDao.getObjectPropertyStatementsForIndividualByProperty(subjectUri, propertyUri, getQueryString()); List<Map<String, String>> statementData = opDao.getObjectPropertyStatementsForIndividualByProperty(subjectUri, propertyUri, getQueryString());
collatedStatements = new HashMap<String, List<ObjectPropertyStatementTemplateModel>>(statementData.size()); subclasses = new HashMap<String, List<ObjectPropertyStatementTemplateModel>>(statementData.size());
// for (Map<String, Object> map : statementData) { // for (Map<String, Object> map : statementData) {
// statements.add(new ObjectPropertyStatementTemplateModel(subjectUri, propertyUri, map, wdf)); // statements.add(new ObjectPropertyStatementTemplateModel(subjectUri, propertyUri, map, wdf));
// } // }
if (statementData.size() > 0) { // if (statementData.size() > 0) {
String collationTarget = getCollationTarget(); // String collationTarget = getCollationTarget();
List<VClass> vclasses = getDirectVClasses(collationTarget, statementData); // List<VClass> vclasses = getDirectVClasses(collationTarget, statementData);
} // }
} }
@ -92,7 +92,7 @@ public class CollatedObjectPropertyTemplateModel extends ObjectPropertyTemplateM
/* Access methods for templates */ /* Access methods for templates */
public Map<String, List<ObjectPropertyStatementTemplateModel>> getCollatedStatements() { public Map<String, List<ObjectPropertyStatementTemplateModel>> getCollatedStatements() {
return collatedStatements; return subclasses;
} }
@Override @Override

View file

@ -19,24 +19,12 @@ public class ObjectPropertyStatementTemplateModel extends BaseTemplateModel {
private String subjectUri; // we'll use these to make the edit links private String subjectUri; // we'll use these to make the edit links
private String propertyUri; private String propertyUri;
private Map<String, Object> data; private Map<String, String> data;
private WebappDaoFactory wdf;
ObjectPropertyStatementTemplateModel(String subjectUri, String propertyUri, Map<String, Object> data, WebappDaoFactory wdf) { ObjectPropertyStatementTemplateModel(String subjectUri, String propertyUri, Map<String, String> data) {
this.subjectUri = subjectUri; this.subjectUri = subjectUri;
this.propertyUri = propertyUri; this.propertyUri = propertyUri;
this.wdf = wdf; this.data = data;
this.data = new HashMap<String, Object>(data.size());
// See comments above the StatementObject class definition on why we don't just set this.data = data.
for (String key : data.keySet()) {
Object value = data.get(key);
if (value instanceof Individual) {
Individual i = (Individual) value;
this.data.put(key, new StatementObject(i));
} else {
this.data.put(key, value);
}
}
} }
/* This is a hopefully temporary solution to account for the fact that in the default /* This is a hopefully temporary solution to account for the fact that in the default
@ -75,28 +63,7 @@ public class ObjectPropertyStatementTemplateModel extends BaseTemplateModel {
* object getProfileUrl(String uri), so in the template we call ${statement.profileUrl(object)} (but still the semantics * object getProfileUrl(String uri), so in the template we call ${statement.profileUrl(object)} (but still the semantics
* is a bit weird, since the profile url doesn't belong to the statement). * is a bit weird, since the profile url doesn't belong to the statement).
*/ */
public class StatementObject {
private Individual individual;
StatementObject(Individual individual) {
this.individual = individual;
}
/* Access methods for templates */
public String getName() {
return individual.getName();
}
public String getMoniker() {
return individual.getMoniker();
}
public String getUrl() {
return UrlBuilder.getIndividualProfileUrl(individual, wdf);
}
}
/* Access methods for templates */ /* Access methods for templates */

View file

@ -3,6 +3,8 @@
package edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual; package edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual;
import java.io.File; import java.io.File;
import java.util.List;
import java.util.Map;
import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.DocumentBuilderFactory;
@ -15,6 +17,7 @@ import org.w3c.dom.NodeList;
import edu.cornell.mannlib.vitro.webapp.beans.Individual; import edu.cornell.mannlib.vitro.webapp.beans.Individual;
import edu.cornell.mannlib.vitro.webapp.beans.ObjectProperty; import edu.cornell.mannlib.vitro.webapp.beans.ObjectProperty;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder;
import edu.cornell.mannlib.vitro.webapp.dao.ObjectPropertyDao; import edu.cornell.mannlib.vitro.webapp.dao.ObjectPropertyDao;
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
@ -45,6 +48,11 @@ public abstract class ObjectPropertyTemplateModel extends PropertyTemplateModel
return config.collationTarget; return config.collationTarget;
} }
protected String getLinkTarget() {
return config.linkTarget;
}
protected static ObjectPropertyTemplateModel getObjectPropertyTemplateModel(ObjectProperty op, Individual subject, WebappDaoFactory wdf) { protected static ObjectPropertyTemplateModel getObjectPropertyTemplateModel(ObjectProperty op, Individual subject, WebappDaoFactory wdf) {
if (op.getCollateBySubclass()) { if (op.getCollateBySubclass()) {
try { try {
@ -58,6 +66,23 @@ public abstract class ObjectPropertyTemplateModel extends PropertyTemplateModel
} }
} }
/** Applies preprocessing to query results to prepare for template */
protected void preprocess(List<Map<String, String>> data, WebappDaoFactory wdf) {
/* First apply standard post-processing for all object properties */
// Add urls for link targets to the data
String linkTarget = config.linkTarget;
for (Map<String, String> map : data) {
String targetUri = map.get(linkTarget);
if (targetUri != null) {
String targetUrl = UrlBuilder.getIndividualProfileUrl(targetUri, wdf);
map.put(linkTarget + "Url", targetUrl);
}
}
/* Then apply custom post-processing specified in config */
}
private class PropertyListConfig { private class PropertyListConfig {
private static final String DEFAULT_CONFIG_FILE = "objectPropertyList-default.xml"; private static final String DEFAULT_CONFIG_FILE = "objectPropertyList-default.xml";
@ -65,10 +90,14 @@ public abstract class ObjectPropertyTemplateModel extends PropertyTemplateModel
private static final String NODE_NAME_QUERY = "query"; private static final String NODE_NAME_QUERY = "query";
private static final String NODE_NAME_TEMPLATE = "template"; private static final String NODE_NAME_TEMPLATE = "template";
private static final String NODE_NAME_COLLATION_TARGET = "collation-target"; private static final String NODE_NAME_COLLATION_TARGET = "collation-target";
private static final String NODE_NAME_LINK_TARGET = "link-target";
private static final String NODE_NAME_PREPROCESSOR = "preprocessor";
private String queryString; private String queryString;
private String templateName; private String templateName;
private String collationTarget; private String collationTarget;
private String linkTarget; // we could easily make this a list if we ever want multiple links
private String preprocessor;
PropertyListConfig(ObjectProperty op, WebappDaoFactory wdf) throws Exception { PropertyListConfig(ObjectProperty op, WebappDaoFactory wdf) throws Exception {
@ -93,9 +122,13 @@ public abstract class ObjectPropertyTemplateModel extends PropertyTemplateModel
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder(); DocumentBuilder db = dbf.newDocumentBuilder();
Document doc = db.parse(configFilePath); Document doc = db.parse(configFilePath);
// Required values
queryString = getConfigValue(doc, NODE_NAME_QUERY); queryString = getConfigValue(doc, NODE_NAME_QUERY);
templateName = getConfigValue(doc, NODE_NAME_TEMPLATE); templateName = getConfigValue(doc, NODE_NAME_TEMPLATE);
// Optional values
collationTarget = getConfigValue(doc, NODE_NAME_COLLATION_TARGET); collationTarget = getConfigValue(doc, NODE_NAME_COLLATION_TARGET);
linkTarget = getConfigValue(doc, NODE_NAME_LINK_TARGET); // if this is null, no link will be generated
preprocessor = getConfigValue(doc, NODE_NAME_PREPROCESSOR);
} catch (Exception e) { } catch (Exception e) {
log.error("Error processing config file " + configFilePath + " for object property " + op.getURI(), e); log.error("Error processing config file " + configFilePath + " for object property " + op.getURI(), e);
// What should we do here? // What should we do here?

View file

@ -1,41 +0,0 @@
/* $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.ArrayList;
import java.util.List;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.web.templatemodels.BaseTemplateModel;
/** List of object property statements for an individual, where the objects belong to a single subclass **/
// RY ** This can probably be eliminated. It can be a map of subclass name to statements.
public class SubclassList extends BaseTemplateModel {
private static final Log log = LogFactory.getLog(SubclassList.class);
String name;
List<ObjectPropertyStatementTemplateModel> statements;
SubclassList(String name) {
this.name = name;
this.statements = new ArrayList<ObjectPropertyStatementTemplateModel>();
// get the obj property statements for this subclass from the db via a sparql query
}
/* Access methods for templates */
public String getName() {
return name;
}
public List<ObjectPropertyStatementTemplateModel> getStatements() {
return statements;
}
}

View file

@ -25,10 +25,11 @@ public class UncollatedObjectPropertyTemplateModel extends ObjectPropertyTemplat
ObjectPropertyStatementDao opDao = wdf.getObjectPropertyStatementDao(); ObjectPropertyStatementDao opDao = wdf.getObjectPropertyStatementDao();
String subjectUri = subject.getURI(); String subjectUri = subject.getURI();
String propertyUri = op.getURI(); String propertyUri = op.getURI();
List<Map<String, Object>> statementData = opDao.getObjectPropertyStatementsForIndividualByProperty(subjectUri, propertyUri, getQueryString()); List<Map<String, String>> statementData = opDao.getObjectPropertyStatementsForIndividualByProperty(subjectUri, propertyUri, getQueryString());
preprocess(statementData, wdf);
statements = new ArrayList<ObjectPropertyStatementTemplateModel>(statementData.size()); statements = new ArrayList<ObjectPropertyStatementTemplateModel>(statementData.size());
for (Map<String, Object> map : statementData) { for (Map<String, String> map : statementData) {
statements.add(new ObjectPropertyStatementTemplateModel(subjectUri, propertyUri, map, wdf)); statements.add(new ObjectPropertyStatementTemplateModel(subjectUri, propertyUri, map));
} }
} }

View file

@ -0,0 +1,13 @@
package edu.cornell.mannlib.vitro.webapp.web.templatemodels.preprocessors;
import java.util.List;
import java.util.Map;
public abstract class BaseObjectPropertyDataPreprocessor implements
ObjectPropertyDataPreprocessor {
@Override
public abstract void preprocess(List<Map<String, String>> data);
}

View file

@ -0,0 +1,17 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.web.templatemodels.preprocessors;
import java.util.List;
import java.util.Map;
public class DefaultObjectPropertyDataPreprocessor extends
BaseObjectPropertyDataPreprocessor {
@Override
public void preprocess(List<Map<String, String>> data) {
// TODO Auto-generated method stub
}
}

View file

@ -0,0 +1,20 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.web.templatemodels.preprocessors;
import java.util.List;
import java.util.Map;
/**
* These preprocessors take a list of object property statement data derived from a
* SPARQL query (or other source) and prepare it for insertion into the template data model.
*
* @author rjy7
*
*/
public interface ObjectPropertyDataPreprocessor {
public void preprocess(List<Map<String, String>> data);
}

View file

@ -2,12 +2,21 @@
<!-- $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$ -->
<view-config> <view-config>
<query> <query>
SELECT ?object { PREFIX vitro: &lt;http://vitro.mannlib.cornell.edu/ns/vitro/0.7#&gt;
PREFIX rdfs: &lt;http://www.w3.org/2000/01/rdf-schema#&gt;
SELECT ?object ?name ?moniker {
?subject ?property ?object . ?subject ?property ?object .
OPTIONAL { ?object rdfs:label ?name . }
OPTIONAL { ?object vitro:moniker ?moniker . }
} }
</query> </query>
<collation-target>object</collation-target> <collation-target>object</collation-target>
<template>objectPropertyList-default.ftl</template> <link-target>object</link-target>
<preprocessor></preprocessor>
<template>shortView-default.ftl</template>
</view-config> </view-config>

View file

@ -2,10 +2,6 @@
<#-- Template for property listing on individual profile page --> <#-- Template for property listing on individual profile page -->
<#-- RY Just a temporary fix to prevent classgroup heading from being pushed to the right edge of the page.
Feel free to redo/remove. -->
<#--><div style="clear: both;" />-->
<#list propertyGroups as group> <#list propertyGroups as group>
<#-- Get the group name --> <#-- Get the group name -->
@ -17,7 +13,7 @@ Feel free to redo/remove. -->
<#assign groupName = "other"> <#assign groupName = "other">
</#if> </#if>
<#else> <#else>
<#-- If there are no groups, a dummy group has been created with a null name. --> <#-- If there are no groups, a dummy group has been created with a null (as opposed to empty) name. -->
<#assign groupName = ""> <#assign groupName = "">
</#if> </#if>
@ -28,32 +24,27 @@ Feel free to redo/remove. -->
<h2><a name="${groupName}"></a>${groupName}</h2 <h2><a name="${groupName}"></a>${groupName}</h2
</#if> </#if>
<#-- Now list the properties in the group --> <#-- List the properties in the group -->
<#list group.properties as property>
<#list group.properties as property>
<article class="property-group" role="article"> <article class="property-group" role="article">
<#-- Property display name --> <#-- Property display name -->
<h3>${property.name}</h3> <h3>${property.name}</h3>
<#-- List the statements for each property --> <#-- List the statements for each property -->
<#if property.type == "data"> <#-- data property --> <#-- data property -->
<#if property.type == "data">
<#list property.statements as statement> <#list property.statements as statement>
<p class="data-property">${statement.value}</p> <p class="data-property">${statement.value}</p>
<!-- end data-prop-stmt-value -->
</#list> </#list>
<#else> <#-- object property --> <#-- object property -->
<#if property.collatedBySubclass> <#elseif property.collatedBySubclass>
<#include "objectPropertyList-collated.ftl"> <#include "objectPropertyList-collated.ftl">
<#else> <#else>
<ul class="object-property" role="list"> <#include "objectPropertyList-statements.ftl">
<#include "${property.template}">
</ul> <!-- end obj-prop-stmt-obj -->
</#if>
</#if> </#if>
<!-- end property --> </article>
</article>
</#list> </#list>
<!-- end properties --> </section>
</section> <!-- end property-group -->
</#list> </#list>

View file

@ -1,7 +0,0 @@
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
<#-- Default object property list template -->
<#list property.statements as statement>
<li role="listitem"><a href="${statement.object.url}">${statement.object.name}</a> | ${statement.object.moniker!}</li>
</#list>

View file

@ -0,0 +1,10 @@
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
<#-- Template to list statements for an object property -->
<ul class="object-property" role="list">
<#list property.statements as statement>
<li role="listitem">
<#include "${property.template}">
</li>
</#list>
</ul>

View file

@ -0,0 +1,5 @@
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
<#-- Default object property statement template -->
<a href="${statement.objectUrl}">${statement.name!"object name here"}</a> ${statement.moniker!"moniker here"}