diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/filtering/ObjectPropertyStatementDaoFiltering.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/filtering/ObjectPropertyStatementDaoFiltering.java index 3bf301ca7..8b8c37da7 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/filtering/ObjectPropertyStatementDaoFiltering.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/filtering/ObjectPropertyStatementDaoFiltering.java @@ -89,4 +89,12 @@ class ObjectPropertyStatementDaoFiltering extends BaseFiltering implements Objec return innerObjectPropertyStatementDao.getObjectPropertyStatementsForIndividualByProperty(subjectUri, propertyUri, query); } + +// @Override +// // RY What about filtering? +// public Map>> getCollatedObjectPropertyStatementsForIndividual( +// String subjectUri, String propertyUri, String query) { +// return innerObjectPropertyStatementDao.getCollatedObjectPropertyStatementsForIndividual(subjectUri, propertyUri, query); +// } + } \ No newline at end of file diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/CollatedObjectPropertyTemplateModel.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/CollatedObjectPropertyTemplateModel.java index d6709cb93..bffe01d3c 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/CollatedObjectPropertyTemplateModel.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/CollatedObjectPropertyTemplateModel.java @@ -2,37 +2,54 @@ package edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual; -import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; 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.ObjectProperty; +import edu.cornell.mannlib.vitro.webapp.beans.VClass; +import edu.cornell.mannlib.vitro.webapp.dao.ObjectPropertyStatementDao; import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; public class CollatedObjectPropertyTemplateModel extends ObjectPropertyTemplateModel { private static final Log log = LogFactory.getLog(CollatedObjectPropertyTemplateModel.class); - private List subclassList; + private Map> collatedStatements; + //private List subclassList; - CollatedObjectPropertyTemplateModel(ObjectProperty property, Individual subject, WebappDaoFactory wdf) { - super(property, subject, wdf); - subclassList = new ArrayList(); + CollatedObjectPropertyTemplateModel(ObjectProperty op, Individual subject, WebappDaoFactory wdf) { + super(op, subject, wdf); + ObjectPropertyStatementDao opDao = wdf.getObjectPropertyStatementDao(); + String subjectUri = subject.getURI(); + String propertyUri = op.getURI(); + List> statementData = opDao.getObjectPropertyStatementsForIndividualByProperty(subjectUri, propertyUri, getQueryString()); + collatedStatements = new HashMap>(statementData.size()); +// for (Map map : statementData) { +// statements.add(new ObjectPropertyStatementTemplateModel(subjectUri, propertyUri, map, wdf)); +// } + + if (statementData.size() > 0) { + String collationTarget = getCollationTarget(); + List vclasses = getDirectVClasses(collationTarget, statementData); + } + } - public List getSubclassList() { - return subclassList; + private List getDirectVClasses(String key, List> data) { + return null; } - -// public List getStatements() { -// return subclassList; -// } - + /* Access methods for templates */ + public Map> getCollatedStatements() { + return collatedStatements; + } + @Override public boolean isCollatedBySubclass() { return true; diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/ObjectPropertyStatementTemplateModel.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/ObjectPropertyStatementTemplateModel.java index 6dc42d267..dafc2330b 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/ObjectPropertyStatementTemplateModel.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/ObjectPropertyStatementTemplateModel.java @@ -27,7 +27,7 @@ public class ObjectPropertyStatementTemplateModel extends BaseTemplateModel { this.propertyUri = propertyUri; this.wdf = wdf; this.data = new HashMap(data.size()); - // See comments above StatementIndividual class definition on why we don't just set this.data = data. + // 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) { @@ -40,9 +40,11 @@ public class ObjectPropertyStatementTemplateModel extends BaseTemplateModel { } /* This is a hopefully temporary solution to account for the fact that in the default - * object property list view we are displaying the object's name and moniker. 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. But in general we do not want to display context nodes + * 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 @@ -50,16 +52,28 @@ public class ObjectPropertyStatementTemplateModel extends BaseTemplateModel { * 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. + * 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). */ public class StatementObject { @@ -69,6 +83,8 @@ public class ObjectPropertyStatementTemplateModel extends BaseTemplateModel { this.individual = individual; } + /* Access methods for templates */ + public String getName() { return individual.getName(); } @@ -89,13 +105,6 @@ public class ObjectPropertyStatementTemplateModel extends BaseTemplateModel { return data.get(key); } - -// public IndividualTemplateModel getIndividual(String key) { -// IndividualDao iDao = vreq.getWebappDaoFactory().getIndividualDao(); -// Individual individual = iDao.getIndividualByURI(data.get(key)); -// return new IndividualTemplateModel(individual, vreq); -// } - public String getEditLink() { return null; } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/ObjectPropertyTemplateModel.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/ObjectPropertyTemplateModel.java index 0c7fdc3e1..126fc49e3 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/ObjectPropertyTemplateModel.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/ObjectPropertyTemplateModel.java @@ -4,6 +4,7 @@ package edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual; import java.io.File; import java.util.List; +import java.util.Map; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; @@ -16,6 +17,7 @@ import org.w3c.dom.NodeList; import edu.cornell.mannlib.vitro.webapp.beans.Individual; import edu.cornell.mannlib.vitro.webapp.beans.ObjectProperty; +import edu.cornell.mannlib.vitro.webapp.dao.ObjectPropertyStatementDao; import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; public abstract class ObjectPropertyTemplateModel extends PropertyTemplateModel { @@ -35,10 +37,16 @@ public abstract class ObjectPropertyTemplateModel extends PropertyTemplateModel protected String getQueryString() { return config.queryString; } + + protected String getCollationTarget() { + return config.collationTarget; + } protected static ObjectPropertyTemplateModel getObjectPropertyTemplateModel(ObjectProperty op, Individual subject, WebappDaoFactory wdf) { - return op.getCollateBySubclass() ? new CollatedObjectPropertyTemplateModel(op, subject, wdf) - : new UncollatedObjectPropertyTemplateModel(op, subject, wdf); +// Temporarily comment out, since collation not working. Display as uncollated for now. +// return op.getCollateBySubclass() ? new CollatedObjectPropertyTemplateModel(op, subject, wdf) +// : new UncollatedObjectPropertyTemplateModel(op, subject, wdf); + return new UncollatedObjectPropertyTemplateModel(op, subject, wdf); } private class PropertyListConfig { @@ -47,9 +55,11 @@ public abstract class ObjectPropertyTemplateModel extends PropertyTemplateModel private static final String CONFIG_FILE_PATH = "/views/"; 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 String queryString; private String templateName; + private String collationTarget; PropertyListConfig(ObjectProperty op) { String filename = DEFAULT_CONFIG_FILE;; @@ -60,19 +70,20 @@ public abstract class ObjectPropertyTemplateModel extends PropertyTemplateModel String configFilename = getConfigFilename(filename); try { - File config = new File(configFilename); - if (configFilename != DEFAULT_CONFIG_FILE && ! config.exists()) { - log.warn("Can't find config file " + configFilename + " for object property " + op.getURI() + "\n" + - ". Using default config file instead."); - configFilename = getConfigFilename(DEFAULT_CONFIG_FILE); - // Should we test for the existence of the default, and throw an error if it doesn't exist? - } + File config = new File(configFilename); + if (configFilename != DEFAULT_CONFIG_FILE && ! config.exists()) { + log.warn("Can't find config file " + configFilename + " for object property " + op.getURI() + "\n" + + ". Using default config file instead."); + configFilename = getConfigFilename(DEFAULT_CONFIG_FILE); + // Should we test for the existence of the default, and throw an error if it doesn't exist? + } - DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(configFilename); queryString = getConfigValue(doc, NODE_NAME_QUERY); templateName = getConfigValue(doc, NODE_NAME_TEMPLATE); + collationTarget = getConfigValue(doc, NODE_NAME_COLLATION_TARGET); } catch (Exception e) { log.error("Error processing config file " + configFilename + " for object property " + op.getURI(), e); // What should we do here? diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/SubclassList.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/SubclassList.java index a3bf9551d..b94f08e39 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/SubclassList.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/SubclassList.java @@ -12,6 +12,8 @@ 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); diff --git a/webapp/web/templates/freemarker/body/individual/individual-properties.ftl b/webapp/web/templates/freemarker/body/individual/individual-properties.ftl index 65021b247..f37b07a5c 100644 --- a/webapp/web/templates/freemarker/body/individual/individual-properties.ftl +++ b/webapp/web/templates/freemarker/body/individual/individual-properties.ftl @@ -2,6 +2,10 @@ <#-- 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. --> +
+ <#list propertyGroups as group> <#-- Get the group name --> @@ -40,10 +44,10 @@ <#else> <#-- object property --> - <#if ! property.collatedBySubclass> - <#include "${property.template}"> - <#else> + <#if property.collatedBySubclass> <#include "objectPropertyList-collated.ftl"> + <#else> + <#include "${property.template}">
diff --git a/webapp/web/templates/freemarker/body/individual/individual.ftl b/webapp/web/templates/freemarker/body/individual/individual.ftl index 2d4cb10fc..463ce0fd8 100644 --- a/webapp/web/templates/freemarker/body/individual/individual.ftl +++ b/webapp/web/templates/freemarker/body/individual/individual.ftl @@ -135,4 +135,4 @@ ${headScripts.add("/js/jquery_plugins/getUrlParam.js", "http://www.google.com/jsapi?autoload=%7B%22modules%22%3A%5B%7B%22name%22%3A%22visualization%22%2C%22version%22%3A%221%22%2C%22packages%22%3A%5B%22areachart%22%2C%22imagesparkline%22%5D%7D%5D%7D", "/js/toggle.js")} -${scripts.add("/js/imageUpload/imageUploadUtils.js")} \ No newline at end of file +${scripts.add("/js/imageUpload/imageUploadUtils.js")} diff --git a/webapp/web/views/objectPropertyList-default.xml b/webapp/web/views/objectPropertyList-default.xml index b1f22334c..00282c162 100644 --- a/webapp/web/views/objectPropertyList-default.xml +++ b/webapp/web/views/objectPropertyList-default.xml @@ -7,5 +7,7 @@ } + object + \ No newline at end of file