NIHVIVO-1510 Collation of properties using default list view. NIHVIVO-1569 Fixed a bug in BaseObjectPropertyDataPostProcessor.removeDuplicates()

This commit is contained in:
rjy7 2011-01-05 19:48:50 +00:00
parent 587e83f6b1
commit 25a818efa9
6 changed files with 90 additions and 70 deletions

View file

@ -2,6 +2,7 @@
package edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
@ -58,11 +59,14 @@ public abstract class BaseObjectPropertyDataPostProcessor implements
return;
}
List<String> foundObjects = new ArrayList<String>();
for (Map<String, String> map : data) {
log.debug("Processing property: " + objectPropertyTemplateModel.getUri());
Iterator<Map<String, String>> dataIterator = data.iterator();
while (dataIterator.hasNext()) {
Map<String, String> map = dataIterator.next();
String objectValue = map.get(objectVariableName);
// We arbitrarily remove all but the first. Not sure what selection criteria could be brought to bear on this.
if (foundObjects.contains(objectValue)) {
data.remove(map);
dataIterator.remove();
} else {
foundObjects.add(objectValue);
}

View file

@ -26,36 +26,27 @@ import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
public class CollatedObjectPropertyTemplateModel extends ObjectPropertyTemplateModel {
private static final Log log = LogFactory.getLog(CollatedObjectPropertyTemplateModel.class);
private static final String DEFAULT_CONFIG_FILE = "listViewConfig-default-collated.xml";
private SortedMap<String, List<ObjectPropertyStatementTemplateModel>> subclasses;
CollatedObjectPropertyTemplateModel(ObjectProperty op, Individual subject, VitroRequest vreq) throws Exception {
super(op, subject, vreq);
// RY Temporarily throw an error because collation hasn't been implemented yet.
// boolean error = true;
// if (error) {
// throw new Exception("Collated object property not implemented yet");
// }
/* Change the approach to collation:
* Custom views can get the subclasses in the query. Must use a term ?subclass - throw error if not.
* Default view: we may be able to figure out the class to get subclasses of by inspecting the property.
* If not, use getDirectClasses etc of the object term.
* We need a subclassed and nonsubclassed default query for the default view: collated-query and uncollated-query.
* We can also use these for custom views. Throw error if property is collated but there's no subclass term
* in the query. (The reverse is okay - uncollated property with a subclass term in the query.
*/
/* Get the data */
WebappDaoFactory wdf = vreq.getWebappDaoFactory();
ObjectPropertyStatementDao opDao = wdf.getObjectPropertyStatementDao();
String subjectUri = subject.getURI();
String propertyUri = op.getURI();
List<Map<String, String>> statementData = opDao.getObjectPropertyStatementsForIndividualByProperty(subjectUri, propertyUri, getQueryString());
List<Map<String, String>> statementData =
opDao.getObjectPropertyStatementsForIndividualByProperty(subjectUri, propertyUri, getQueryString());
/* Apply postprocessing */
postprocess(statementData, wdf);
Map<String, List<ObjectPropertyStatementTemplateModel>> unsortedSubclasses = hasDefaultListView() ?
collateDefaultListView(subjectUri, propertyUri, statementData, vreq) :
collateCustomListView(subjectUri, propertyUri, statementData, vreq);
/* Collate the data */
Map<String, List<ObjectPropertyStatementTemplateModel>> unsortedSubclasses =
collate(subjectUri, propertyUri, statementData, vreq);
/* Sort by subclass name */
Comparator<String> comparer = new Comparator<String>() {
@ -67,10 +58,10 @@ public class CollatedObjectPropertyTemplateModel extends ObjectPropertyTemplateM
subclasses.putAll(unsortedSubclasses);
}
private Map<String, List<ObjectPropertyStatementTemplateModel>> collateCustomListView(String subjectUri,
private Map<String, List<ObjectPropertyStatementTemplateModel>> collate(String subjectUri,
String propertyUri, List<Map<String, String>> statementData, VitroRequest vreq) {
Map<String, List<ObjectPropertyStatementTemplateModel>> unsortedSubclasses =
Map<String, List<ObjectPropertyStatementTemplateModel>> subclassMap =
new HashMap<String, List<ObjectPropertyStatementTemplateModel>>();
String currentSubclassUri = null;
List<ObjectPropertyStatementTemplateModel> currentList = null;
@ -80,19 +71,11 @@ public class CollatedObjectPropertyTemplateModel extends ObjectPropertyTemplateM
currentSubclassUri = subclassUri;
currentList = new ArrayList<ObjectPropertyStatementTemplateModel>();
String subclassName = getSubclassName(subclassUri, vreq);
unsortedSubclasses.put(subclassName, currentList);
subclassMap.put(subclassName, currentList);
}
currentList.add(new ObjectPropertyStatementTemplateModel(subjectUri, propertyUri, map));
}
return unsortedSubclasses;
}
private Map<String, List<ObjectPropertyStatementTemplateModel>> collateDefaultListView(String subjectUri,
String propertyUri, List<Map<String, String>> statementData, VitroRequest vreq) {
Map<String, List<ObjectPropertyStatementTemplateModel>> unsortedSubclasses =
new HashMap<String, List<ObjectPropertyStatementTemplateModel>>();
return unsortedSubclasses;
return subclassMap;
}
private String getSubclassName(String subclassUri, VitroRequest vreq) {
@ -100,30 +83,12 @@ public class CollatedObjectPropertyTemplateModel extends ObjectPropertyTemplateM
VClass vclass = vclassDao.getVClassByURI(subclassUri);
return vclass.getName();
}
private String getCollationTargetError() {
String errorMessage = null;
String collationTarget = getCollationTarget();
// Make sure the collation target is not null or empty.
if (collationTarget == null || collationTarget.trim().isEmpty()) {
errorMessage = "No collation target specified.";
} else {
// Make sure the collation target is one of the select terms in the query.
String queryString = getQueryString();
String selectClause = queryString.substring(0, queryString.indexOf("{"));
Pattern collationTargetPattern = Pattern.compile("\\b\\\\?" + collationTarget + "\\b");
Matcher matcher = collationTargetPattern.matcher(selectClause);
if (! matcher.find()) {
errorMessage = "Invalid collation target.";
}
}
return errorMessage;
}
private List<VClass> getDirectVClasses(String key, List<Map<String, Object>> data) {
return null;
}
@Override
protected String getDefaultConfigFileName() {
return DEFAULT_CONFIG_FILE;
}
/* Access methods for templates */
public Map<String, List<ObjectPropertyStatementTemplateModel>> getSubclasses() {

View file

@ -55,11 +55,7 @@ public abstract class ObjectPropertyTemplateModel extends PropertyTemplateModel
protected String getQueryString() {
return config.queryString;
}
protected String getCollationTarget() {
return config.collationTarget;
}
protected boolean hasDefaultListView() {
return config.isDefaultConfig;
}
@ -95,19 +91,18 @@ public abstract class ObjectPropertyTemplateModel extends PropertyTemplateModel
}
}
protected abstract String getDefaultConfigFileName();
private class PropertyListConfig {
private static final String DEFAULT_CONFIG_FILE = "listViewConfig-default.xml";
private static final String CONFIG_FILE_PATH = "/config/";
private static final String NODE_NAME_QUERY = "query";
private static final String NODE_NAME_TEMPLATE = "template";
private static final String NODE_NAME_COLLATION_TARGET = "collation-target";
private static final String NODE_NAME_POSTPROCESSOR = "postprocessor";
private boolean isDefaultConfig;
private String queryString;
private String templateName;
private String collationTarget;
private String postprocessor;
PropertyListConfig(ObjectProperty op, VitroRequest vreq) throws Exception {
@ -117,7 +112,7 @@ public abstract class ObjectPropertyTemplateModel extends PropertyTemplateModel
ObjectPropertyDao opDao = wdf.getObjectPropertyDao();
String configFileName = opDao.getCustomListConfigFileName(op);
if (configFileName == null) { // no custom config; use default config
configFileName = DEFAULT_CONFIG_FILE;
configFileName = getDefaultConfigFileName();
}
log.debug("Using list view config file " + configFileName + " for object property " + op.getURI());
@ -127,7 +122,7 @@ public abstract class ObjectPropertyTemplateModel extends PropertyTemplateModel
if ( ! isDefaultConfig(configFileName) && ! config.exists() ) {
log.warn("Can't find config file " + configFilePath + " for object property " + op.getURI() + "\n" +
". Using default config file instead.");
configFilePath = getConfigFilePath(DEFAULT_CONFIG_FILE);
configFilePath = getConfigFilePath(getDefaultConfigFileName());
// Should we test for the existence of the default, and throw an error if it doesn't exist?
}
setValuesFromConfigFile(configFilePath);
@ -143,7 +138,7 @@ public abstract class ObjectPropertyTemplateModel extends PropertyTemplateModel
log.warn("Invalid list view config for object property " + op.getURI() +
" in " + configFilePath + ":\n" +
invalidConfigMessage + " Using default config instead.");
configFilePath = getConfigFilePath(DEFAULT_CONFIG_FILE);
configFilePath = getConfigFilePath(getDefaultConfigFileName());
setValuesFromConfigFile(configFilePath);
}
}
@ -152,7 +147,7 @@ public abstract class ObjectPropertyTemplateModel extends PropertyTemplateModel
}
private boolean isDefaultConfig(String configFileName) {
return configFileName.equals(DEFAULT_CONFIG_FILE);
return configFileName.equals(getDefaultConfigFileName());
}
private String checkForInvalidConfig(VitroRequest vreq) {
@ -189,7 +184,6 @@ public abstract class ObjectPropertyTemplateModel extends PropertyTemplateModel
templateName = getConfigValue(doc, NODE_NAME_TEMPLATE);
// Optional values
collationTarget = getConfigValue(doc, NODE_NAME_COLLATION_TARGET);
postprocessor = getConfigValue(doc, NODE_NAME_POSTPROCESSOR);
} catch (Exception e) {
log.error("Error processing config file " + configFilePath, e);

View file

@ -18,23 +18,35 @@ import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
public class UncollatedObjectPropertyTemplateModel extends ObjectPropertyTemplateModel {
private static final Log log = LogFactory.getLog(UncollatedObjectPropertyTemplateModel.class);
private static final String DEFAULT_CONFIG_FILE = "listViewConfig-default-uncollated.xml";
private List<ObjectPropertyStatementTemplateModel> statements;
UncollatedObjectPropertyTemplateModel(ObjectProperty op, Individual subject, VitroRequest vreq) {
super(op, subject, vreq);
/* Get the data */
WebappDaoFactory wdf = vreq.getWebappDaoFactory();
ObjectPropertyStatementDao opDao = wdf.getObjectPropertyStatementDao();
String subjectUri = subject.getURI();
String propertyUri = op.getURI();
List<Map<String, String>> statementData = opDao.getObjectPropertyStatementsForIndividualByProperty(subjectUri, propertyUri, getQueryString());
/* Apply postprocessing */
postprocess(statementData, wdf);
/* Put into data structure to send to template */
statements = new ArrayList<ObjectPropertyStatementTemplateModel>(statementData.size());
for (Map<String, String> map : statementData) {
statements.add(new ObjectPropertyStatementTemplateModel(subjectUri, propertyUri, map));
}
}
@Override
protected String getDefaultConfigFileName() {
return DEFAULT_CONFIG_FILE;
}
/* Access methods for templates */
public List<ObjectPropertyStatementTemplateModel> getStatements() {

View file

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
<!--
Default list view config file for collated object properties
Required elements:
- query: the sparql query used to retrieve the data
- template: the name of the template used to display a single property statement
Optional elements:
- postprocessor: a Java class that postprocesses the data retrieved from the query before
sending it to the template
Query requirements:
- WHERE clause must contain a statement ?subject ?property ?object, with the variables
?subject and ?property named as such. The object can be given any name, but it must be
included in the SELECT terms retrieved by the query. This is the statement that will be edited
from the edit links.
- Each assertion or set of optional assertions must reference a different graph variable, so that
we do not impose a requirement about which assertions are in the same graph.
-->
<list-view-config>
<query>
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 ?subclass ?object ?name ?moniker {
GRAPH ?g1 { ?subject ?property ?object }
OPTIONAL { GRAPH ?g2 { ?object rdfs:label ?name } }
OPTIONAL { GRAPH ?g3 { ?object vitro:moniker ?moniker } }
OPTIONAL { GRAPH ?g4 { ?object a ?subclass }
FILTER (?g4 != &lt;http://vitro.mannlib.cornell.edu/default/inferred-tbox&gt; &amp;&amp;
?g4 != &lt;http://vitro.mannlib.cornell.edu/default/vitro-kb-inf&gt; )
}
}
</query>
<postprocessor>edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual.DefaultListViewDataPostProcessor</postprocessor>
<template>propStatement-default.ftl</template>
</list-view-config>

View file

@ -1,7 +1,9 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
<!--
<!--
Default list view config file for uncollated object properties
Required elements:
- query: the sparql query used to retrieve the data
- template: the name of the template used to display a single property statement