NIHVIVO-3300 Placeholder images are configured by a properties file, which is loaded at startup.

This commit is contained in:
j2blake 2012-03-22 20:10:18 +00:00
parent 94717a3705
commit 9442468b75
10 changed files with 278 additions and 79 deletions

View file

@ -24,7 +24,7 @@ import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues;
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
import edu.cornell.mannlib.vitro.webapp.utils.ImageUtil;
import edu.cornell.mannlib.vitro.webapp.web.images.PlaceholderUtil;
/**
* TODO
@ -134,8 +134,8 @@ public class ManageProxiesListPage extends AbstractPageHandler {
private ProxyItemInfo wrapProxyItem(ProxyItemInfo item) {
String imagePath = item.getImageUrl();
if (imagePath.isEmpty()) {
imagePath = ImageUtil
.getPlaceholderImagePathForType(VitroVocabulary.USERACCOUNT);
imagePath = PlaceholderUtil.getPlaceholderImagePathForType(vreq,
VitroVocabulary.USERACCOUNT);
}
UserAccount ua = userAccountsDao.getUserAccountByUri(item.getUri());
@ -151,8 +151,8 @@ public class ManageProxiesListPage extends AbstractPageHandler {
private ProxyItemInfo wrapProfileItem(ProxyItemInfo item) {
String imagePath = item.getImageUrl();
if (imagePath.isEmpty()) {
imagePath = ImageUtil.getPlaceholderImagePathForIndividual(vreq,
item.getUri());
imagePath = PlaceholderUtil.getPlaceholderImagePathForIndividual(
vreq, item.getUri());
}
return new ProfileItemWrapper(item.getUri(), item.getLabel(),

View file

@ -24,9 +24,9 @@ import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder;
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
import edu.cornell.mannlib.vitro.webapp.dao.jena.ModelContext;
import edu.cornell.mannlib.vitro.webapp.dao.jena.OntModelSelector;
import edu.cornell.mannlib.vitro.webapp.utils.ImageUtil;
import edu.cornell.mannlib.vitro.webapp.utils.SparqlQueryRunner;
import edu.cornell.mannlib.vitro.webapp.utils.SparqlQueryUtils;
import edu.cornell.mannlib.vitro.webapp.web.images.PlaceholderUtil;
/**
* Get the basic auto-complete info for the proxy selection.
@ -64,8 +64,9 @@ public class BasicProxiesGetter extends AbstractAjaxResponder {
OntModelSelector oms = ModelContext.getUnionOntModelSelector(ctx);
userAccountsModel = oms.getUserAccountsModel();
placeholderImageUrl = UrlBuilder.getUrl(ImageUtil
.getPlaceholderImagePathForType(VitroVocabulary.USERACCOUNT));
placeholderImageUrl = UrlBuilder.getUrl(PlaceholderUtil
.getPlaceholderImagePathForType(vreq,
VitroVocabulary.USERACCOUNT));
}
@Override

View file

@ -19,7 +19,7 @@ import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.controller.ajax.AbstractAjaxResponder;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder;
import edu.cornell.mannlib.vitro.webapp.dao.ObjectPropertyStatementDao;
import edu.cornell.mannlib.vitro.webapp.utils.ImageUtil;
import edu.cornell.mannlib.vitro.webapp.web.images.PlaceholderUtil;
/**
* Get more information (class label and image URL) about a selected proxy.
@ -79,7 +79,7 @@ public class MoreProfileInfo extends AbstractAjaxResponder {
private String getFullImageUrl(Individual ind) {
String path = ind.getThumbUrl();
if ((path == null) || path.isEmpty()) {
path = ImageUtil.getPlaceholderImagePathForIndividual(vreq,
path = PlaceholderUtil.getPlaceholderImagePathForIndividual(vreq,
ind.getURI());
}
return UrlBuilder.getUrl(path);

View file

@ -27,7 +27,7 @@ import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues;
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
import edu.cornell.mannlib.vitro.webapp.utils.ImageUtil;
import edu.cornell.mannlib.vitro.webapp.web.images.PlaceholderUtil;
/**
* Handle the "My Account" form display and submission.
@ -270,8 +270,9 @@ public class UserAccountsMyAccountPage extends UserAccountsPage {
String userUri = proxyUser.getUri();
String label = assembleUserAccountLabel(proxyUser);
String classLabel = "";
String imageUrl = UrlBuilder.getUrl(ImageUtil
.getPlaceholderImagePathForType(VitroVocabulary.USERACCOUNT));
String imageUrl = UrlBuilder.getUrl(PlaceholderUtil
.getPlaceholderImagePathForType(vreq,
VitroVocabulary.USERACCOUNT));
// Does this user have a profile? Can we get better info?
Individual proxyProfilePage = getProfilePage(proxyUser);

View file

@ -36,7 +36,7 @@ import edu.cornell.mannlib.vitro.webapp.filestorage.backend.FileStorageSetup;
import edu.cornell.mannlib.vitro.webapp.filestorage.model.FileInfo;
import edu.cornell.mannlib.vitro.webapp.filestorage.model.ImageInfo;
import edu.cornell.mannlib.vitro.webapp.filestorage.uploadrequest.FileUploadServletRequest;
import edu.cornell.mannlib.vitro.webapp.utils.ImageUtil;
import edu.cornell.mannlib.vitro.webapp.web.images.PlaceholderUtil;
/**
* Handle adding, replacing or deleting the main image on an Individual.
@ -405,8 +405,9 @@ public class ImageUploadController extends FreemarkerHttpServlet {
ACTION_UPLOAD);
String cancelUrl = (entity == null) ? "" : exitPageUrl(vreq,
entity.getURI());
String placeholderUrl = (entity == null) ? "" : UrlBuilder.getUrl(ImageUtil
.getPlaceholderImagePathForIndividual(vreq, entity.getURI()));
String placeholderUrl = (entity == null) ? "" : UrlBuilder
.getUrl(PlaceholderUtil.getPlaceholderImagePathForIndividual(
vreq, entity.getURI()));
TemplateResponseValues rv = new TemplateResponseValues(TEMPLATE_NEW);

View file

@ -1,61 +0,0 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.utils;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.dao.IndividualDao;
/**
* Some static methods that help in dealing with image files.
*/
public class ImageUtil {
private static final String DEFAULT_IMAGE_PATH = "/images/placeholders/thumbnail.jpg";
private static final Map<String, String> DEFAULT_IMAGE_PATHS_BY_TYPE = initImagePaths();
private static Map<String, String> initImagePaths() {
Map<String, String> map = new HashMap<String, String>();
// No images other than the default.
return Collections.unmodifiableMap(map);
}
/**
* If we have a placeholder image for this exact type, return it. Otherwise,
* return the default.
*/
public static String getPlaceholderImagePathForType(String typeUri) {
for (Entry<String, String> entry : DEFAULT_IMAGE_PATHS_BY_TYPE
.entrySet()) {
if (typeUri.equals(entry.getKey())) {
return entry.getValue();
}
}
return DEFAULT_IMAGE_PATH;
}
/**
* If there is a placeholder image for any type that this Individual
* instantiates, return that image. Otherwise, return the default.
*/
public static String getPlaceholderImagePathForIndividual(
VitroRequest vreq, String individualUri) {
IndividualDao indDao = vreq.getWebappDaoFactory().getIndividualDao();
for (Entry<String, String> entry : DEFAULT_IMAGE_PATHS_BY_TYPE
.entrySet()) {
if (indDao.isIndividualOfClass(entry.getKey(), individualUri)) {
return entry.getValue();
}
}
return DEFAULT_IMAGE_PATH;
}
/** Never need to instantiate this -- all methods are static. */
private ImageUtil() {
// Nothing to do
}
}

View file

@ -0,0 +1,238 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.web.images;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.Map.Entry;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.dao.IndividualDao;
import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus;
/**
* A utility for finding the URL of the correct Placeholder image.
*
* The mapping of image URLs to classes is created at startup, and stored in the
* ServletContext.
*/
public class PlaceholderUtil {
private static final Log log = LogFactory.getLog(PlaceholderUtil.class);
private static final String ATTRIBUTE_NAME = PlaceholderUtil.class
.getName();
private static final String PROPERTIES_FILE_PATH = "/images/placeholders/placeholders.properties";
private static final String DEFAULT_IMAGE_PATH = "/images/placeholders/thumbnail.jpg";
// ----------------------------------------------------------------------
// Static methods
// ----------------------------------------------------------------------
/**
* If we have a placeholder image for this exact type, return it. Otherwise,
* return the default.
*/
public static String getPlaceholderImagePathForType(VitroRequest vreq,
String typeUri) {
PlaceholderUtil pu = getPlaceholderUtil(vreq);
if (pu == null) {
return DEFAULT_IMAGE_PATH;
} else {
return pu.getPlaceholderImagePathForType(typeUri);
}
}
/**
* If there is a placeholder image for any type that this Individual
* instantiates, return that image. Otherwise, return the default.
*/
public static String getPlaceholderImagePathForIndividual(
VitroRequest vreq, String individualUri) {
PlaceholderUtil pu = getPlaceholderUtil(vreq);
if (pu == null) {
return DEFAULT_IMAGE_PATH;
} else {
IndividualDao iDao = vreq.getWebappDaoFactory().getIndividualDao();
return pu.getPlaceholderImagePathForIndividual(iDao, individualUri);
}
}
/** Get the PlaceholderUtil instance from the context, or null if none. */
private static PlaceholderUtil getPlaceholderUtil(VitroRequest vreq) {
if (vreq == null) {
return null;
}
ServletContext ctx = vreq.getSession().getServletContext();
Object attrib = ctx.getAttribute(ATTRIBUTE_NAME);
if (attrib instanceof PlaceholderUtil) {
return (PlaceholderUtil) attrib;
} else {
log.warn("Looked for a PlaceholerUtil, but found " + attrib);
return null;
}
}
// ----------------------------------------------------------------------
// The object
// ----------------------------------------------------------------------
private final Map<String, String> mapUrlsByClass;
private PlaceholderUtil(Map<String, String> map) {
this.mapUrlsByClass = Collections
.unmodifiableMap(new HashMap<String, String>(map));
}
/**
* If we have a placeholder image for this exact type, return it. Otherwise,
* return the default.
*/
private String getPlaceholderImagePathForType(String typeUri) {
if (typeUri == null) {
log.debug("getPlaceholderImagePathForType: typeUri is null");
return DEFAULT_IMAGE_PATH;
}
String url = mapUrlsByClass.get(typeUri);
if (url == null) {
log.debug("getPlaceholderImagePathForType: no value for '"
+ typeUri + "'");
return DEFAULT_IMAGE_PATH;
}
log.debug("getPlaceholderImagePathForType: value for '" + typeUri
+ "' is '" + url + "'");
return url;
}
/**
* If there is a placeholder image for any type that this Individual
* instantiates, return that image. Otherwise, return the default.
*/
private String getPlaceholderImagePathForIndividual(IndividualDao iDao,
String individualUri) {
if (individualUri == null) {
log.debug("getPlaceholderImagePathForIndividual: "
+ "individualUri is null");
return DEFAULT_IMAGE_PATH;
}
for (String classUri : mapUrlsByClass.keySet()) {
String imageUrl = mapUrlsByClass.get(classUri);
if (iDao.isIndividualOfClass(classUri, individualUri)) {
log.debug("getPlaceholderImagePathForIndividual: individual '"
+ individualUri + "' is of class '" + classUri
+ "', value is '" + imageUrl + "'");
return imageUrl;
}
}
log.debug("getPlaceholderImagePathForIndividual: individual '"
+ individualUri + "' is not of any recognized class");
return DEFAULT_IMAGE_PATH;
}
// ----------------------------------------------------------------------
// Classes used for setup
// ----------------------------------------------------------------------
public static class Setup implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
ServletContext ctx = sce.getServletContext();
StartupStatus ss = StartupStatus.getBean(ctx);
try {
File propertiesFile = confirmRealPath(ctx, PROPERTIES_FILE_PATH);
Map<String, String> map = loadPropertiesToMap(propertiesFile);
confirmImagesArePresent(ctx, map);
ctx.setAttribute(ATTRIBUTE_NAME, new PlaceholderUtil(map));
} catch (SetupException e) {
if (e.getCause() == null) {
ss.warning(this, e.getMessage());
} else {
ss.warning(this, e.getMessage(), e.getCause());
}
}
}
private Map<String, String> loadPropertiesToMap(File propertiesFile)
throws SetupException {
Properties props = new Properties();
try {
props.load(new FileReader(propertiesFile));
} catch (IOException e) {
throw new SetupException(
"Can't load properties from the file at '"
+ PROPERTIES_FILE_PATH
+ "'. Is it in a valid format?", e);
}
Map<String, String> map = new HashMap<String, String>();
for (Enumeration<Object> keys = props.keys(); keys
.hasMoreElements();) {
String key = (String) keys.nextElement();
String value = props.getProperty(key);
map.put(key, value);
}
return map;
}
private void confirmImagesArePresent(ServletContext ctx,
Map<String, String> map) throws SetupException {
Set<String> imageUrls = new HashSet<String>();
imageUrls.add(DEFAULT_IMAGE_PATH);
imageUrls.addAll(map.values());
for (String imageUrl : imageUrls) {
confirmRealPath(ctx, imageUrl);
}
}
private File confirmRealPath(ServletContext ctx, String url)
throws SetupException {
String path = ctx.getRealPath(url);
if (path == null) {
throw new SetupException("Can't translate to real path: '"
+ url + "'");
}
File file = new File(path);
if (!file.exists()) {
throw new SetupException("No file found at '" + url + "'.");
}
if (!file.canRead()) {
throw new SetupException("Can't read the file at '" + url
+ "'.");
}
return file;
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
sce.getServletContext().removeAttribute(ATTRIBUTE_NAME);
}
}
private static class SetupException extends Exception {
public SetupException(String message) {
super(message);
}
public SetupException(String message, Throwable cause) {
super(message, cause);
}
}
}

View file

@ -11,7 +11,7 @@ import javax.servlet.http.HttpServletRequest;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder;
import edu.cornell.mannlib.vitro.webapp.utils.ImageUtil;
import edu.cornell.mannlib.vitro.webapp.web.images.PlaceholderUtil;
import freemarker.core.Environment;
import freemarker.template.TemplateModelException;
@ -32,7 +32,7 @@ public class IndividualPlaceholderImageUrlMethod extends BaseTemplateMethodModel
Environment env = Environment.getCurrentEnvironment();
HttpServletRequest request = (HttpServletRequest) env.getCustomAttribute("request");
VitroRequest vreq = new VitroRequest(request);
String imageUrl = ImageUtil.getPlaceholderImagePathForIndividual(vreq, uri);
String imageUrl = PlaceholderUtil.getPlaceholderImagePathForIndividual(vreq, uri);
return UrlBuilder.getUrl(imageUrl);
}

View file

@ -24,6 +24,8 @@ edu.cornell.mannlib.vitro.webapp.servlet.setup.UpdateKnowledgeBase
edu.cornell.mannlib.vitro.webapp.filestorage.backend.FileStorageSetup
edu.cornell.mannlib.vitro.webapp.web.images.PlaceholderUtil$Setup
# Update the URIs on Permission Sets on UserAccounts from model (1.4) to 1.5.
edu.cornell.mannlib.vitro.webapp.servlet.setup.UpdatePermissionSetUris

View file

@ -0,0 +1,17 @@
#
# Assign placeholder images to classes of individuals.
#
# If showing an individual that has no image, a placeholder image may be shown.
# By default, the placeholder is /images/placeholders/thumbnail.jpg. However,
# this file allows you to associate classes with special placeholder images, and
# if the individual belongs to such a class, the special placeholder is shown
# instead of the default.
#
# EXAMPLE:
# http\://xmlns.com/foaf/0.1/Person = /images/placeholders/person.thumbnail.jpg
# means that any individual of type foaf:Person will be represented by
# person.thumbnail.jpg
#
# NOTE: a colon is a special character in a properties file, and must be escaped
# by a backslash.