NIHVIVO-1332 Editing links for vitro:primaryLink and vitro:additionalLink properties

This commit is contained in:
rjy7 2011-01-13 21:11:19 +00:00
parent 981aff8ac4
commit dbbe25b65c
13 changed files with 190 additions and 70 deletions

View file

@ -3,6 +3,7 @@
package edu.cornell.mannlib.vitro.webapp.dao.jena;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
@ -55,12 +56,36 @@ import edu.cornell.mannlib.vitro.webapp.dao.VClassDao;
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
import edu.cornell.mannlib.vitro.webapp.dao.jena.event.EditEvent;
import edu.cornell.mannlib.vitro.webapp.dao.jena.pellet.PelletListener;
import edu.cornell.mannlib.vitro.webapp.utils.StringUtils;
public class DataPropertyDaoJena extends PropertyDaoJena implements
DataPropertyDao {
protected static final Log log = LogFactory.getLog(DataPropertyDaoJena.class.getName());
/* This may be the intent behind JenaBaseDao.NONUSER_NAMESPACES, but that
* value does not contain all of these namespaces.
*/
protected static final List<String> EXCLUDED_NAMESPACES = Arrays.asList(
"http://vitro.mannlib.cornell.edu/ns/vitro/0.7#",
"http://vitro.mannlib.cornell.edu/ns/vitro/public#",
"http://www.w3.org/1999/02/22-rdf-syntax-ns#",
"http://www.w3.org/2000/01/rdf-schema#",
"http://www.w3.org/2002/07/owl#"
);
/*
* This is a hack to throw out properties in the vitro, rdf, rdfs, and owl namespaces.
* It will be implemented in a better way in v1.3 (Editing and Display Configuration).
*/
protected static String propertyFilters = null;
static {
List<String> namespaceFilters = new ArrayList<String>();
for (String s : EXCLUDED_NAMESPACES) {
namespaceFilters.add("afn:namespace(?property) != \"" + s + "\"");
}
propertyFilters = "FILTER (" + StringUtils.join(namespaceFilters, " && \n") + ")\n";
}
protected static final String dataPropertyQueryString =
PREFIXES + "\n" +
"SELECT DISTINCT ?property WHERE { \n" +

View file

@ -3,6 +3,7 @@
package edu.cornell.mannlib.vitro.webapp.dao.jena;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
@ -48,10 +49,38 @@ import edu.cornell.mannlib.vitro.webapp.dao.ObjectPropertyDao;
import edu.cornell.mannlib.vitro.webapp.dao.OntologyDao;
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
import edu.cornell.mannlib.vitro.webapp.dao.jena.event.EditEvent;
import edu.cornell.mannlib.vitro.webapp.utils.StringUtils;
public class ObjectPropertyDaoJena extends PropertyDaoJena implements ObjectPropertyDao {
private static final Log log = LogFactory.getLog(ObjectPropertyDaoJena.class.getName());
/* This may be the intent behind JenaBaseDao.NONUSER_NAMESPACES, but that
* value does not contain all of these namespaces.
*/
protected static final List<String> EXCLUDED_NAMESPACES = Arrays.asList(
//"http://vitro.mannlib.cornell.edu/ns/vitro/0.7#",
//"http://vitro.mannlib.cornell.edu/ns/vitro/public#",
"http://www.w3.org/1999/02/22-rdf-syntax-ns#",
"http://www.w3.org/2000/01/rdf-schema#",
"http://www.w3.org/2002/07/owl#"
);
/*
* This is a hack to throw out properties in the vitro, rdf, rdfs, and owl namespaces.
* It will be implemented in a better way in v1.3 (Editing and Display Configuration).
*/
protected static String propertyFilters = "";
static {
List<String> namespaceFilters = new ArrayList<String>();
for (String s : EXCLUDED_NAMESPACES) {
namespaceFilters.add("afn:namespace(?property) != \"" + s + "\"");
}
// A hack to include the vitro:primaryLink and vitro:additionalLink properties in the list
// namespaceFilters.add("( ?property = <http://vitro.mannlib.cornell.edu/ns/vitro/0.7#primaryLink> ||" +
// "?property = <http://vitro.mannlib.cornell.edu/ns/vitro/0.7#additionalLink> ||" +
// "afn:namespace(?property) != \"http://vitro.mannlib.cornell.edu/ns/vitro/0.7#\" )");
propertyFilters = "FILTER (" + StringUtils.join(namespaceFilters, " && \n") + ")\n";
}
protected static final String objectPropertyQueryString =
PREFIXES + "\n" +
"SELECT DISTINCT ?property WHERE { \n" +

View file

@ -47,28 +47,6 @@ public class PropertyDaoJena extends JenaBaseDao implements PropertyDao {
"PREFIX vitro: <http://vitro.mannlib.cornell.edu/ns/vitro/0.7#> \n" +
"PREFIX owl: <http://www.w3.org/2002/07/owl#> \n" +
"PREFIX afn: <http://jena.hpl.hp.com/ARQ/function#>";
/* This may be the intent behind JenaBaseDao.NONUSER_NAMESPACES, but that
* value does not contain all of these namespaces.
*/
protected static final List<String> EXCLUDED_NAMESPACES = Arrays.asList(
"http://vitro.mannlib.cornell.edu/ns/vitro/0.7#",
"http://vitro.mannlib.cornell.edu/ns/vitro/public#",
"http://www.w3.org/1999/02/22-rdf-syntax-ns#",
"http://www.w3.org/2000/01/rdf-schema#",
"http://www.w3.org/2002/07/owl#"
);
/*
* This is a hack to throw out properties in the vitro, rdf, rdfs, and owl namespaces.
* It will be implemented in a better way in v1.3 (Editing and Display Configuration).
*/
protected static String propertyFilters = "";
static {
for (String s : EXCLUDED_NAMESPACES) {
propertyFilters += "FILTER (afn:namespace(?property) != \"" + s + "\") \n";
}
}
private DatasetWrapperFactory dwf;

View file

@ -6,7 +6,9 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@ -23,6 +25,7 @@ import edu.cornell.mannlib.vitro.webapp.dao.DataPropertyDao;
import edu.cornell.mannlib.vitro.webapp.dao.ObjectPropertyDao;
import edu.cornell.mannlib.vitro.webapp.dao.PropertyGroupDao;
import edu.cornell.mannlib.vitro.webapp.dao.PropertyInstanceDao;
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
import edu.cornell.mannlib.vitro.webapp.filters.VitroRequestPrep;
import edu.cornell.mannlib.vitro.webapp.web.templatemodels.BaseTemplateModel;
@ -42,6 +45,12 @@ public class GroupedPropertyList extends BaseTemplateModel {
private static final Log log = LogFactory.getLog(GroupedPropertyList.class);
private static final int MAX_GROUP_DISPLAY_RANK = 99;
private static final List<String> VITRO_PROPS_TO_ADD_TO_LIST = new ArrayList<String>() {{
add(VitroVocabulary.PRIMARY_LINK);
add(VitroVocabulary.ADDITIONAL_LINK);
//add(VitroVocabulary.IND_MAIN_IMAGE);
}};
private Individual subject;
private VitroRequest vreq;
private WebappDaoFactory wdf;
@ -142,30 +151,39 @@ public class GroupedPropertyList extends BaseTemplateModel {
PropertyInstanceDao piDao = wdf.getPropertyInstanceDao();
Collection<PropertyInstance> allPropInstColl = piDao.getAllPossiblePropInstForIndividual(subject.getURI());
if (allPropInstColl != null) {
ObjectPropertyDao opDao = wdf.getObjectPropertyDao();
for (PropertyInstance pi : allPropInstColl) {
if (pi != null) {
// RY Do we need to check this before checking if it's on the property list??
if (! alreadyOnObjectPropertyList(objectPropertyList, pi)) {
ObjectPropertyDao opDao = wdf.getObjectPropertyDao();
ObjectProperty op = opDao.getObjectPropertyByURI(pi.getPropertyURI());
if (op == null) {
log.error("ObjectProperty op returned null from opDao.getObjectPropertyByURI()");
} else if (op.getURI() == null) {
log.error("ObjectProperty op returned with null propertyURI from opDao.getObjectPropertyByURI()");
} else if (! alreadyOnPropertyList(propertyList, op)) {
//op.setLabel(op.getDomainPublic());
propertyList.add(op);
}
addIfNotAlreadyOnList(propertyList, pi.getPropertyURI(), opDao);
}
} else {
log.error("a property instance in the Collection created by PropertyInstanceDao.getAllPossiblePropInstForIndividual() is unexpectedly null");
}
}
// These properties are outside the ontologies (in vitro and vitro public) but need to be added to the list
// In future, vitro ns props will be phased out. Vitro public properties should be changed so they do no
// constitute a special case.
for (String propertyUri : VITRO_PROPS_TO_ADD_TO_LIST) {
addIfNotAlreadyOnList(propertyList, propertyUri, opDao);
}
} else {
log.error("a null Collection is returned from PropertyInstanceDao.getAllPossiblePropInstForIndividual()");
}
}
private void addIfNotAlreadyOnList(List<Property> propertyList, String propertyUri, ObjectPropertyDao opDao) {
ObjectProperty op = opDao.getObjectPropertyByURI(propertyUri);
if (op == null) {
log.error("ObjectProperty op returned null from opDao.getObjectPropertyByURI()");
} else if (op.getURI() == null) {
log.error("ObjectProperty op returned with null propertyURI from opDao.getObjectPropertyByURI()");
} else if (! alreadyOnPropertyList(propertyList, op)) {
propertyList.add(op);
}
}
protected void mergeAllPossibleDataProperties(List<Property> propertyList) {
DataPropertyDao dpDao = wdf.getDataPropertyDao();
Collection <DataProperty> allDatapropColl = dpDao.getAllPossibleDatapropsForIndividual(subject.getURI());

View file

@ -16,8 +16,6 @@ import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder.Route;
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
import edu.cornell.mannlib.vitro.webapp.filters.VitroRequestPrep;
import edu.cornell.mannlib.vitro.webapp.web.ViewFinder;
import edu.cornell.mannlib.vitro.webapp.web.ViewFinder.ClassView;
import edu.cornell.mannlib.vitro.webapp.web.templatemodels.BaseTemplateModel;
public class IndividualTemplateModel extends BaseTemplateModel {
@ -68,6 +66,7 @@ public class IndividualTemplateModel extends BaseTemplateModel {
return isPerson() ? getUrl(Route.VISUALIZATION_AJAX.path(), "uri", getUri()) : null;
}
// ** Remove these when the new methods are written
public String getImageUrl() {
String imageUrl = individual.getImageUrl();
return imageUrl == null ? null : getUrl(imageUrl);
@ -133,7 +132,7 @@ public class IndividualTemplateModel extends BaseTemplateModel {
links.addAll(additionalLinks);
return links;
}
public GroupedPropertyList getPropertyList() {
if (propertyList == null) {
propertyList = new GroupedPropertyList(individual, vreq, policyHelper);

View file

@ -43,11 +43,26 @@ public class ListedIndividualTemplateModel extends BaseTemplateModel {
return models;
}
private String getView(ClassView view) {
ViewFinder vf = new ViewFinder(view);
return vf.findClassView(individual, vreq);
}
/* Access methods for templates */
public String getProfileUrl() {
return UrlBuilder.getIndividualProfileUrl(individual, vreq.getWebappDaoFactory());
}
public String getImageUrl() {
String imageUrl = individual.getImageUrl();
return imageUrl == null ? null : getUrl(imageUrl);
}
public String getThumbUrl() {
String thumbUrl = individual.getThumbUrl();
return thumbUrl == null ? null : getUrl(thumbUrl);
}
public Link getPrimaryLink() {
Link primaryLink = null;
@ -92,13 +107,4 @@ public class ListedIndividualTemplateModel extends BaseTemplateModel {
return getView(ClassView.SEARCH);
}
public String getDisplayView() {
return getView(ClassView.DISPLAY);
}
private String getView(ClassView view) {
ViewFinder vf = new ViewFinder(view);
return vf.findClassView(individual, vreq);
}
}

View file

@ -2,8 +2,6 @@
package edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
@ -14,17 +12,16 @@ import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.propstmt.DropObject
import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.propstmt.EditObjPropStmt;
import edu.cornell.mannlib.vitro.webapp.beans.ObjectPropertyStatement;
import edu.cornell.mannlib.vitro.webapp.beans.ObjectPropertyStatementImpl;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder.ParamMap;
import edu.cornell.mannlib.vitro.webapp.web.templatemodels.BaseTemplateModel;
import edu.cornell.mannlib.vitro.webapp.dao.ObjectPropertyStatementDao;
public class ObjectPropertyStatementTemplateModel extends PropertyStatementTemplateModel {
private static final Log log = LogFactory.getLog(ObjectPropertyStatementTemplateModel.class);
private static final String EDIT_PATH = "edit/editRequestDispatch.jsp";
private Map<String, String> data;
@ -36,12 +33,30 @@ public class ObjectPropertyStatementTemplateModel extends PropertyStatementTempl
super(subjectUri, propertyUri, policyHelper);
this.data = data;
objectUri = data.get(objectKey);
setEditAccess(policyHelper);
}
/**
* This method handles the special case where we are creating a DataPropertyStatementTemplateModel
* outside the GroupedPropertyList. Specifically, it allows vitro:primaryLink and vitro:additionalLink
* to be treated like data property statements and thus have editing links. (In a future version,
* these properties will be replaced by vivo core ontology properties.) It could potentially be used
* for other properties outside the property list as well.
*/
ObjectPropertyStatementTemplateModel(String subjectUri, String propertyUri,
VitroRequest vreq, EditingPolicyHelper policyHelper) {
super(subjectUri, propertyUri, policyHelper);
ObjectPropertyStatementDao opsDao = vreq.getWebappDaoFactory().getObjectPropertyStatementDao();
}
private void setEditAccess(EditingPolicyHelper policyHelper) {
// If the policyHelper is non-null, we are in edit mode, so create the list of editing permissions.
// We do this now rather than in getEditUrl() and getDeleteUrl(), because getEditUrl() also needs to know
// whether a delete is allowed.
if (policyHelper != null) {
objectUri = data.get(objectKey);
ObjectPropertyStatement objectPropertyStatement = new ObjectPropertyStatementImpl(subjectUri, propertyUri, objectUri);
// Determine whether the statement can be edited
@ -55,9 +70,8 @@ public class ObjectPropertyStatementTemplateModel extends PropertyStatementTempl
if (policyHelper.isAuthorizedAction(action)) {
markDeletable();
}
}
}
}
/* Access methods for templates */

View file

@ -94,6 +94,7 @@ public abstract class ObjectPropertyTemplateModel extends PropertyTemplateModel
}
}
protected String getQueryString() {
return config.queryString;
}

View file

@ -0,0 +1,22 @@
<?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
See guidelines in vitro/doc/list_view_configuration_guidelines.txt -->
<list-view-config>
<query>
PREFIX vitro: &lt;http://vitro.mannlib.cornell.edu/ns/vitro/0.7#&gt;
PREFIX afn: &lt;http://jena.hpl.hp.com/ARQ/function#&gt;
SELECT ?link (afn:localname(?link) AS ?linkName) ?anchor ?url WHERE {
GRAPH ?g1 { ?subject ?property ?link }
OPTIONAL { GRAPH ?g2 { ?link vitro:linkAnchor ?anchor } }
OPTIONAL { GRAPH ?g3 { ?link vitro:linkURL ?url } }
OPTIONAL { GRAPH ?g4 { ?link vitro:linkDisplayRank ?rank } }
} ORDER BY ?rank
</query>
<template>propStatement-vitroLink.ftl</template>
</list-view-config>

View file

@ -161,27 +161,27 @@ ul#individual-phone li:first-child{
.icon-phone, .icon-email{
padding-right: 5px;
}
ul#individual-urls{
ul.individual-urls{
list-style-type: circle;
margin-left: 10px;
float: left;
margin-bottom: 30px;
}
ul#individual-urls li{
ul.individual-urls li{
font-size: .875em;
line-height: 1.2em;
}
ul#individual-urls li a{
ul.individual-urls li a{
color: #2485ae;
}
ul#individual-urls-people{
ul.individual-urls-people{
clear: both;
margin-top: 20px;
list-style: none;
list-style-type: circle;
padding-left: 24px;
}
ul#individual-urls-people li{
ul.individual-urls-people li{
font-size: .875em;
line-height: 1.2em;
}

View file

@ -6,10 +6,24 @@
will use the vivo core ontology links property, eliminating the need for special handling.
-->
<nav role="navigation">
<ul id ="individual-urls" role="list">
<#list individual.links as link>
<li role="listitem"><a href="${link.url}">${link.anchor}</a></li>
</#list>
</ul>
</nav>
<#assign vitroNs = "http://vitro.mannlib.cornell.edu/ns/vitro/0.7#">
<#assign primaryLink = propertyGroups.getPropertyAndRemoveFromList("${vitroNs}primaryLink")!>
<#assign additionalLinks = propertyGroups.getPropertyAndRemoveFromList("${vitroNs}additionalLink")!>
<#assign linkListClass = linkListClass!"individual-urls">
<#if (primaryLink?has_content || additionalLinks?has_content)> <#-- true when the property is in the list, even if not populated (when editing) -->
<nav role="navigation">
<@p.addLinkWithLabel primaryLink editing "Primary Web Page" />
<#if primaryLink.statements?has_content> <#-- if there are any statements -->
<ul class="${linkListClass}" id="links-primary" role="list">
<@p.objectPropertyList primaryLink.statements primaryLink.template editing />
</ul>
</#if>
<@p.addLinkWithLabel additionalLinks editing "Additional Web Pages" />
<#if additionalLinks.statements?has_content> <#-- if there are any statements -->
<ul class="${linkListClass}" id="links-additional" role="list">
<@p.objectPropertyList additionalLinks.statements additionalLinks.template editing />
</ul>
</#if>
</nav>
</#if>

View file

@ -33,11 +33,12 @@
</#macro>
<#-- Some properties usually display without a label. But if there's an add link,
we need to also show the property label. -->
<#macro addLinkWithLabel property showEditingLinks>
we need to also show the property label. If no label is specified, the property
name will be used as the label. -->
<#macro addLinkWithLabel property showEditingLinks label="${property.name?capitalize}">
<#local addLink><@addLink property showEditingLinks /></#local>
<#if addLink?has_content>
<h3>${property.name?capitalize} ${addLink}</h3>
<h3>${label} ${addLink}</h3>
</#if>
</#macro>
@ -77,5 +78,3 @@ we need to also show the property label. -->
<a href="${url}" title="delete this relationship"><img class="delete-individual" src="${urls.images}/individual/deleteIcon.gif" alt="delete" /></a>
</#if>
</#macro>
<#-- Macros for specific properties -->

View file

@ -0,0 +1,15 @@
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
<#-- Template for vitro:primaryLink and vitro:additionalLink -->
<#assign linkText>
<#if statement.anchor??>${statement.anchor}
<#else>${statement.linkName} (no anchor text provided for link)
</#if>
</#assign>
<#if statement.url??>
<a href="${statement.url}">${linkText}</a>
<#else>
<a href="${profileUrl(statement.link)}">${linkText}</a> (no url provided for link)
</#if>