NIHVIVO-1341 Preprocessing of object property data for list views

This commit is contained in:
rjy7 2010-12-16 18:15:44 +00:00
parent d2d91dfe77
commit 7d23fcab5a
10 changed files with 131 additions and 89 deletions

View file

@ -0,0 +1,68 @@
package edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual;
import java.util.List;
import java.util.Map;
import edu.cornell.mannlib.vitro.webapp.beans.Individual;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder;
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
public class BaseObjectPropertyDataPreprocessor implements
ObjectPropertyDataPreprocessor {
protected ObjectPropertyTemplateModel objectPropertyTemplateModel;
protected WebappDaoFactory wdf;
public BaseObjectPropertyDataPreprocessor(ObjectPropertyTemplateModel optm, WebappDaoFactory wdf) {
this.objectPropertyTemplateModel = optm;
this.wdf = wdf;
}
@Override
public void process(List<Map<String, String>> data) {
for (Map<String, String> map : data) {
applyStandardPreprocessing(map);
applySpecificPreprocessing(map);
}
}
/* Standard preprocessing that applies to all views. */
protected void applyStandardPreprocessing(Map<String, String> map) {
addLinkForTarget(map);
}
protected void applySpecificPreprocessing(Map<String, String> map) {
/* Base class method is empty because this method is defined
* to apply subclass preprocessing.
*/
}
private void addLinkForTarget(Map<String, String> map) {
String linkTarget = objectPropertyTemplateModel.getLinkTarget();
String targetUri = map.get(linkTarget);
if (targetUri != null) {
String targetUrl = getLink(targetUri);
map.put(linkTarget + "Url", targetUrl);
}
}
/* Preprocessor helper methods callable from any preprocessor */
protected String getLink(String uri) {
return UrlBuilder.getIndividualProfileUrl(uri, wdf);
}
protected String getMoniker(String uri) {
return getIndividual(uri).getMoniker();
}
protected String getName(String uri) {
return getIndividual(uri).getName();
}
protected Individual getIndividual(String uri) {
return wdf.getIndividualDao().getIndividualByURI(uri);
}
}

View file

@ -0,0 +1,37 @@
/* $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.Map;
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
public class DefaultObjectPropertyDataPreprocessor extends
BaseObjectPropertyDataPreprocessor {
public DefaultObjectPropertyDataPreprocessor(ObjectPropertyTemplateModel optm, WebappDaoFactory wdf) {
super(optm, wdf);
}
@Override
/* Apply preprocessing specific to this preprocessor */
protected void applySpecificPreprocessing(Map<String, String> map) {
addName(map);
addMoniker(map);
}
private void addName(Map<String, String> map) {
String name = map.get("name");
if (name == null) {
map.put("name", getName(map.get("object")));
}
}
private void addMoniker(Map<String, String> map) {
String moniker = map.get("moniker");
if (moniker == null) {
map.put("moniker", getMoniker(map.get("object")));
}
}
}

View file

@ -1,6 +1,6 @@
/* $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$ */
package edu.cornell.mannlib.vitro.webapp.web.templatemodels.preprocessors; package edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -15,6 +15,6 @@ import java.util.Map;
public interface ObjectPropertyDataPreprocessor { public interface ObjectPropertyDataPreprocessor {
public void preprocess(List<Map<String, String>> data); public void process(List<Map<String, String>> data);
} }

View file

@ -27,44 +27,6 @@ public class ObjectPropertyStatementTemplateModel extends BaseTemplateModel {
this.data = data; this.data = data;
} }
/* This is a hopefully temporary solution to account for the fact that in the default
* object property list view we display the object's name and moniker, and these
* cannot be derived from a simple sparql query.
*
* The name is either the label, localName, or id, because context nodes do not have labels
* (and blank nodes do not have local names?). But in general we do not want to display context nodes
* in the property list view; we are only displaying them temporarily until custom list views
* are implemented. In general any object that we want to display in a custom view should have a label,
* and we can get that directly from the sparql query. Note that we can get the localName using an ARQ
* function: PREFIX afn: <http://jena.hpl.hp.com/ARQ/function#>
* SELECT ?object (afn:localname(?object) AS ?localName) ...
* but it is harder (or impossible) to do what the individual.getName() function does in a SPARQL query.
*
* In the case of moniker, the Individual.getMoniker() returns the VClass if moniker is null.
* But moniker is a vitro namespace property which will be eliminated in a future version,
* and the get-vclass-if-no-moniker logic should be moved into the display modules where it belongs.
* In general any information that we would want to display in the custom list view should be obtained
* directly in the sparql query, and that should be generally true for custom queries and views.
*
* We could instead make these methods of the outer class that take a uri parameter, but then the template
* semantics is less intuitive: we would have ${statement.moniker(object)} rather than
* ${statement.object.name}, but the moniker is not a property of the statement.
*
* We don't want to put an Individual into the template model, because the beans wrapper used in IndividualController
* has exposure level EXPOSE_SAFE, due to the need to call methods with parameters rather than simple parameterless
* getters. We don't want to expose the Individual's setters to the template, so we wrap it in an individual that
* only has getters.
*
* RY *** Consider doing this only for the default query. The custom query can just store the data values as strings
* (uri, label, etc.). There should be no issues with label and moniker in a custom query (but is that true, or do
* some custom queries display the moniker?), and to handle url we can create a directive <@profileUrl individual=object />
* where object is the object uri. This will get the WebappDaoFactory from the request and call
* UrlBuilder.getIndividualProfileUrl(String individualUri, WebappDaoFactory wdf). Equivalently, have a method of this
* 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).
*/
/* Access methods for templates */ /* Access methods for templates */

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.io.File; import java.io.File;
import java.lang.reflect.Constructor;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -17,7 +18,6 @@ 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;
@ -25,6 +25,12 @@ public abstract class ObjectPropertyTemplateModel extends PropertyTemplateModel
private static final Log log = LogFactory.getLog(ObjectPropertyTemplateModel.class); private static final Log log = LogFactory.getLog(ObjectPropertyTemplateModel.class);
private static final String TYPE = "object"; private static final String TYPE = "object";
/* NB The default preprocessor is not the same as the preprocessor for the default view. The latter
* actually defines its own preprocessor, whereas the default preprocessor is used for custom views
* that don't define a preprocessor.
*/
private static final String DEFAULT_PREPROCESSOR =
"edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual.BaseObjectPropertyDataPreprocessor";
private PropertyListConfig config; private PropertyListConfig config;
@ -66,21 +72,21 @@ public abstract class ObjectPropertyTemplateModel extends PropertyTemplateModel
} }
} }
/** Applies preprocessing to query results to prepare for template */ /** Apply preprocessing to query results to prepare for template */
protected void preprocess(List<Map<String, String>> data, WebappDaoFactory wdf) { protected void preprocess(List<Map<String, String>> data, WebappDaoFactory wdf) {
/* First apply standard post-processing for all object properties */ String preprocessorName = config.preprocessor;
if (preprocessorName == null) {
// Add urls for link targets to the data preprocessorName = DEFAULT_PREPROCESSOR;
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 */ try {
Class<?> preprocessorClass = Class.forName(preprocessorName);
Constructor<?> constructor = preprocessorClass.getConstructor(ObjectPropertyTemplateModel.class, WebappDaoFactory.class);
ObjectPropertyDataPreprocessor preprocessor = (ObjectPropertyDataPreprocessor) constructor.newInstance(this, wdf);
preprocessor.process(data);
} catch (Exception e) {
log.error(e, e);
}
} }
private class PropertyListConfig { private class PropertyListConfig {

View file

@ -1,13 +0,0 @@
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

@ -1,17 +0,0 @@
/* $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

@ -16,7 +16,7 @@
<link-target>object</link-target> <link-target>object</link-target>
<preprocessor></preprocessor> <preprocessor>edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual.DefaultObjectPropertyDataPreprocessor</preprocessor>
<template>shortView-default.ftl</template> <template>shortView-default.ftl</template>
</view-config> </view-config>

View file

@ -35,7 +35,7 @@
<#-- data property --> <#-- data property -->
<#if property.type == "data"> <#if property.type == "data">
<#list property.statements as statement> <#list property.statements as statement>
<p class="data-property-statement">${statement.value}</p> <li role="listitem">${statement.value}</li>
</#list> </#list>
<#-- object property --> <#-- object property -->
@ -45,8 +45,7 @@
<#include "objectPropertyList-statements.ftl"> <#include "objectPropertyList-statements.ftl">
</#if> </#if>
</ul> </ul>
</article> </article> <!-- end property -->
</#list> </#list>
</section> </section> <!-- end property-group -->
</#list> </#list>

View file

@ -2,4 +2,4 @@
<#-- Default object property statement short view template --> <#-- Default object property statement short view template -->
<a href="${statement.objectUrl}">${statement.name!"object name here"}</a> ${statement.moniker!"moniker here"} <a href="${statement.objectUrl}">${statement.name!}</a> ${statement.moniker!}