NIHVIVO-2018 Move visualization url-building out of templates into template models. Create vivo-specific IndividualTemplateModel for this purpose.

This commit is contained in:
rjy7 2011-02-11 23:04:37 +00:00
parent 22a2dc75d9
commit 70ee4551af
3 changed files with 201 additions and 173 deletions

View file

@ -201,6 +201,12 @@ public class UrlBuilder {
put(key, String.valueOf(value));
}
public void put(ParamMap params) {
for (String key: params.keySet()) {
put(key, params.get(key));
}
}
}
/********** Static utility methods **********/
@ -265,6 +271,10 @@ public class UrlBuilder {
return addParams(url, new ParamMap(params));
}
public static String addParams(String url, List<String> params) {
return addParams(url, new ParamMap(params));
}
public static String getPath(Route route, ParamMap params) {
return getPath(route.path(), params);
}

View file

@ -0,0 +1,188 @@
/* $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.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.openrdf.model.URI;
import org.openrdf.model.impl.URIImpl;
import edu.cornell.mannlib.vedit.beans.LoginStatusBean;
import edu.cornell.mannlib.vitro.webapp.beans.Individual;
import edu.cornell.mannlib.vitro.webapp.beans.VClass;
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.Route;
import edu.cornell.mannlib.vitro.webapp.dao.VClassDao;
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
import edu.cornell.mannlib.vitro.webapp.filters.VitroRequestPrep;
import edu.cornell.mannlib.vitro.webapp.reasoner.SimpleReasoner;
import edu.cornell.mannlib.vitro.webapp.web.templatemodels.BaseTemplateModel;
public abstract class BaseIndividualTemplateModel extends BaseTemplateModel {
private static final Log log = LogFactory.getLog(BaseIndividualTemplateModel.class);
private static final String PATH = Route.INDIVIDUAL.path();
protected Individual individual;
protected VitroRequest vreq;
protected UrlBuilder urlBuilder;
protected GroupedPropertyList propertyList = null;
protected LoginStatusBean loginStatusBean = null;
private EditingPolicyHelper policyHelper = null;
public BaseIndividualTemplateModel(Individual individual, VitroRequest vreq) {
this.individual = individual;
this.vreq = vreq;
this.loginStatusBean = LoginStatusBean.getBean(vreq);
// Needed for getting portal-sensitive urls. Remove if multi-portal support is removed.
this.urlBuilder = new UrlBuilder(vreq.getPortal());
// If editing, create a helper object to check requested actions against policies
if (isEditable()) {
policyHelper = new EditingPolicyHelper(vreq, getServletContext());
}
}
protected boolean isVClass(String vClassUri) {
boolean isVClass = individual.isVClass(vClassUri);
// If reasoning is asynchronous (under RDB), this inference may not have been made yet.
// Check the superclasses of the individual's vclass.
if (!isVClass && SimpleReasoner.isABoxReasoningAsynchronous(getServletContext())) {
log.debug("Checking superclasses to see if individual is a " + vClassUri + " because reasoning is asynchronous");
List<VClass> directVClasses = individual.getVClasses(true);
for (VClass directVClass : directVClasses) {
VClassDao vcDao = vreq.getWebappDaoFactory().getVClassDao();
List<String> superClassUris = vcDao.getAllSuperClassURIs(directVClass.getURI());
if (superClassUris.contains(vClassUri)) {
isVClass = true;
break;
}
}
}
return isVClass;
}
/* These methods perform some manipulation of the data returned by the Individual methods */
public String getProfileUrl() {
return UrlBuilder.getIndividualProfileUrl(individual, vreq.getWebappDaoFactory());
}
// This remains as a convenience method for getting the image url. We could instead use a custom list
// view for mainImage which would provide this data in the query results.
public String getImageUrl() {
String imageUrl = individual.getImageUrl();
return imageUrl == null ? null : getUrl(imageUrl);
}
// This remains as a convenience method for getting the thumbnail url. We could instead use a custom list
// view for mainImage which would provide this data in the query results.
public String getThumbUrl() {
String thumbUrl = individual.getThumbUrl();
return thumbUrl == null ? null : getUrl(thumbUrl);
}
public String getRdfUrl() {
return getRdfUrl(true);
}
// Used to create a link to generate the individual's rdf.
public String getRdfUrl(boolean checkExternalNamespaces) {
String individualUri = getUri();
String profileUrl = getProfileUrl();
URI uri = new URIImpl(individualUri);
String namespace = uri.getNamespace();
// Individuals in the default namespace
// e.g., http://vivo.cornell.edu/individual/n2345/n2345.rdf
// where default namespace = http://vivo.cornell.edu/individual/
String defaultNamespace = vreq.getWebappDaoFactory().getDefaultNamespace();
if (defaultNamespace.equals(namespace)) {
return profileUrl + "/" + getLocalName() + ".rdf";
}
// An RDF url is not defined for an externally linked namespace. The data does not reside
// in the current system, and the external system may not accept a request for rdf.
if (checkExternalNamespaces && vreq.getWebappDaoFactory()
.getApplicationDao()
.isExternallyLinkedNamespace(namespace)) {
return null;
}
// http://some.other.namespace/n2345?format=rdfxml
return UrlBuilder.addParams(profileUrl, "format", "rdfxml");
}
public String getEditUrl() {
return urlBuilder.getPortalUrl(Route.INDIVIDUAL_EDIT, "uri", getUri());
}
public GroupedPropertyList getPropertyList() {
if (propertyList == null) {
propertyList = new GroupedPropertyList(individual, vreq, policyHelper);
}
return propertyList;
}
public boolean isEditable() {
// RY This will be improved later. What is important is not whether the user is a self-editor,
// but whether he has editing privileges on this profile. This is just a crude way of determining
// whether to even bother looking at the editing policies.
return VitroRequestPrep.isSelfEditing(vreq) || loginStatusBean.isLoggedIn();
}
public boolean getShowAdminPanel() {
return loginStatusBean.isLoggedInAtLeast(LoginStatusBean.EDITOR);
}
/* rdfs:label needs special treatment, because it is not possible to construct a
* DataProperty from it. It cannot be handled the way the vitro links and vitro public image
* are handled like ordinary ObjectProperty instances.
*/
public DataPropertyStatementTemplateModel getNameStatement() {
String propertyUri = VitroVocabulary.LABEL; // rdfs:label
DataPropertyStatementTemplateModel dpstm = new DataPropertyStatementTemplateModel(getUri(), propertyUri, vreq, policyHelper);
// If the individual has no rdfs:label, return the local name. It will not be editable (this replicates previous behavior;
// perhaps we would want to allow a label to be added. But such individuals do not usually have their profiles viewed or
// edited directly.
if (dpstm.getValue() == null) {
dpstm.setValue(getLocalName());
}
return dpstm;
}
/* These methods simply forward to the methods of the wrapped individual. It would be desirable to
* implement a scheme for proxying or delegation so that the methods don't need to be simply listed here.
* A Ruby-style method missing method would be ideal.
* Update: DynamicProxy doesn't work because the proxied object is of type Individual, so we cannot
* declare new methods here that are not declared in the Individual interface.
*/
public String getName() {
return individual.getName();
}
public String getMoniker() {
return individual.getMoniker();
}
public String getUri() {
return individual.getURI();
}
public String getLocalName() {
return individual.getLocalName();
}
}

View file

@ -2,188 +2,18 @@
package edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual;
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 org.openrdf.model.URI;
import org.openrdf.model.impl.URIImpl;
import edu.cornell.mannlib.vedit.beans.LoginStatusBean;
import edu.cornell.mannlib.vitro.webapp.beans.Individual;
import edu.cornell.mannlib.vitro.webapp.beans.VClass;
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.Route;
import edu.cornell.mannlib.vitro.webapp.dao.VClassDao;
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
import edu.cornell.mannlib.vitro.webapp.filters.VitroRequestPrep;
import edu.cornell.mannlib.vitro.webapp.reasoner.SimpleReasoner;
import edu.cornell.mannlib.vitro.webapp.web.templatemodels.BaseTemplateModel;
public class IndividualTemplateModel extends BaseTemplateModel {
public class IndividualTemplateModel extends BaseIndividualTemplateModel {
private static final Log log = LogFactory.getLog(IndividualTemplateModel.class);
private static final String PATH = Route.INDIVIDUAL.path();
protected Individual individual;
protected VitroRequest vreq;
protected UrlBuilder urlBuilder;
protected GroupedPropertyList propertyList = null;
protected LoginStatusBean loginStatusBean = null;
private EditingPolicyHelper policyHelper = null;
public IndividualTemplateModel(Individual individual, VitroRequest vreq) {
this.individual = individual;
this.vreq = vreq;
this.loginStatusBean = LoginStatusBean.getBean(vreq);
// Needed for getting portal-sensitive urls. Remove if multi-portal support is removed.
this.urlBuilder = new UrlBuilder(vreq.getPortal());
// If editing, create a helper object to check requested actions against policies
if (isEditable()) {
policyHelper = new EditingPolicyHelper(vreq, getServletContext());
}
super(individual, vreq);
}
// private boolean isVClass(String vClassUri) {
// boolean isVClass = individual.isVClass(vClassUri);
// // If reasoning is asynchronous (under RDB), this inference may not have been made yet.
// // Check the superclasses of the individual's vclass.
// if (!isVClass && SimpleReasoner.isABoxReasoningAsynchronous(getServletContext())) {
// log.debug("Checking superclasses to see if individual is a " + vClassUri + " because reasoning is asynchronous");
// List<VClass> directVClasses = individual.getVClasses(true);
// for (VClass directVClass : directVClasses) {
// VClassDao vcDao = vreq.getWebappDaoFactory().getVClassDao();
// List<String> superClassUris = vcDao.getAllSuperClassURIs(directVClass.getURI());
// if (superClassUris.contains(vClassUri)) {
// isVClass = true;
// break;
// }
// }
// }
// return isVClass;
// }
/* These methods perform some manipulation of the data returned by the Individual methods */
public String getProfileUrl() {
return UrlBuilder.getIndividualProfileUrl(individual, vreq.getWebappDaoFactory());
}
// This remains as a convenience method for getting the image url. We could instead use a custom list
// view for mainImage which would provide this data in the query results.
public String getImageUrl() {
String imageUrl = individual.getImageUrl();
return imageUrl == null ? null : getUrl(imageUrl);
}
// This remains as a convenience method for getting the thumbnail url. We could instead use a custom list
// view for mainImage which would provide this data in the query results.
public String getThumbUrl() {
String thumbUrl = individual.getThumbUrl();
return thumbUrl == null ? null : getUrl(thumbUrl);
}
public String getRdfUrl() {
return getRdfUrl(true);
}
// Used to create a link to generate the individual's rdf.
public String getRdfUrl(boolean checkExternalNamespaces) {
String individualUri = getUri();
String profileUrl = getProfileUrl();
URI uri = new URIImpl(individualUri);
String namespace = uri.getNamespace();
// Individuals in the default namespace
// e.g., http://vivo.cornell.edu/individual/n2345/n2345.rdf
// where default namespace = http://vivo.cornell.edu/individual/
String defaultNamespace = vreq.getWebappDaoFactory().getDefaultNamespace();
if (defaultNamespace.equals(namespace)) {
return profileUrl + "/" + getLocalName() + ".rdf";
}
// An RDF url is not defined for an externally linked namespace. The data does not reside
// in the current system, and the external system may not accept a request for rdf.
if (checkExternalNamespaces && vreq.getWebappDaoFactory()
.getApplicationDao()
.isExternallyLinkedNamespace(namespace)) {
return null;
}
// http://some.other.namespace/n2345?format=rdfxml
return UrlBuilder.addParams(profileUrl, "format", "rdfxml");
}
public String getEditUrl() {
return urlBuilder.getPortalUrl(Route.INDIVIDUAL_EDIT, "uri", getUri());
}
public GroupedPropertyList getPropertyList() {
if (propertyList == null) {
propertyList = new GroupedPropertyList(individual, vreq, policyHelper);
}
return propertyList;
}
public boolean isEditable() {
// RY This will be improved later. What is important is not whether the user is a self-editor,
// but whether he has editing privileges on this profile. This is just a crude way of determining
// whether to even bother looking at the editing policies.
return VitroRequestPrep.isSelfEditing(vreq) || loginStatusBean.isLoggedIn();
}
public boolean getShowAdminPanel() {
return loginStatusBean.isLoggedInAtLeast(LoginStatusBean.EDITOR);
}
/* rdfs:label needs special treatment, because it is not possible to construct a
* DataProperty from it. It cannot be handled the way the vitro links and vitro public image
* are handled like ordinary ObjectProperty instances.
*/
public DataPropertyStatementTemplateModel getNameStatement() {
String propertyUri = VitroVocabulary.LABEL; // rdfs:label
DataPropertyStatementTemplateModel dpstm = new DataPropertyStatementTemplateModel(getUri(), propertyUri, vreq, policyHelper);
// If the individual has no rdfs:label, return the local name. It will not be editable (this replicates previous behavior;
// perhaps we would want to allow a label to be added. But such individuals do not usually have their profiles viewed or
// edited directly.
if (dpstm.getValue() == null) {
dpstm.setValue(getLocalName());
}
return dpstm;
}
/* These methods simply forward to the methods of the wrapped individual. It would be desirable to
* implement a scheme for proxying or delegation so that the methods don't need to be simply listed here.
* A Ruby-style method missing method would be ideal.
* Update: DynamicProxy doesn't work because the proxied object is of type Individual, so we cannot
* declare new methods here that are not declared in the Individual interface.
*/
public String getName() {
return individual.getName();
}
public String getMoniker() {
return individual.getMoniker();
}
public String getUri() {
return individual.getURI();
}
public String getLocalName() {
return individual.getLocalName();
}
}