Updates to ViewFinder class to find custom templates

This commit is contained in:
rjy7 2010-08-25 14:45:02 +00:00
parent d48efa96cf
commit ff0aa17398
4 changed files with 85 additions and 56 deletions

View file

@ -30,6 +30,7 @@ import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder.Route;
import edu.cornell.mannlib.vitro.webapp.utils.StringUtils;
import edu.cornell.mannlib.vitro.webapp.web.BreadCrumbsUtil;
import edu.cornell.mannlib.vitro.webapp.web.PortalWebUtil;
import edu.cornell.mannlib.vitro.webapp.web.templatemodels.BaseTemplateModel;
import edu.cornell.mannlib.vitro.webapp.web.templatemodels.files.Scripts;
import edu.cornell.mannlib.vitro.webapp.web.templatemodels.files.Stylesheets;
import edu.cornell.mannlib.vitro.webapp.web.templatemodels.menu.TabMenu;
@ -57,7 +58,10 @@ public class FreemarkerHttpServlet extends VitroHttpServlet {
try {
VitroRequest vreq = new VitroRequest(request);
BaseTemplateModel.setVitroRequest(vreq);
Configuration config = getConfig(vreq);
vreq.setAttribute("freemarkerConfig", config);
// We can't use shared variables in the Freemarker configuration to store anything
// except theme-specific data, because multiple portals or apps might share the same theme. So instead
@ -127,7 +131,7 @@ public class FreemarkerHttpServlet extends VitroHttpServlet {
config.setTemplateUpdateDelay(60); // in seconds; Freemarker default is 5
}
// Specify how templates will see the data-model.
// Specify how templates will see the data model.
// The default wrapper exposes set methods unless exposure level is set.
// By default we want to block exposure of set methods.
BeansWrapper wrapper = new DefaultObjectWrapper();

View file

@ -2,7 +2,7 @@
package edu.cornell.mannlib.vitro.webapp.web;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
@ -14,7 +14,10 @@ import org.apache.commons.logging.LogFactory;
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.utils.StringUtils;
import freemarker.cache.TemplateLoader;
import freemarker.template.Configuration;
/**
* Class to find custom class views for individuals
@ -23,23 +26,22 @@ import edu.cornell.mannlib.vitro.webapp.utils.StringUtils;
*/
public class ViewFinder {
private static final Log log = LogFactory.getLog(ViewFinder.class.getName());
private static final Log log = LogFactory.getLog(ViewFinder.class);
public enum ClassView {
DISPLAY("getCustomDisplayView", "/view-display"),
// NB this is not the value currently used for custom forms - we use the value on the object property
FORM("getCustomEntryForm", "/form"),
SEARCH("getCustomSearchView", "/view-search"),
SHORT("getCustomShortView", "/view-short");
private static String TEMPLATE_PATH = "/templates/freemarker";
DISPLAY("getCustomDisplayView", "view-display-default.ftl"),
// NB this is not the value currently used for custom forms - we use the value on the object property.
// This value is specifiable from the backend editor, however.
FORM("getCustomEntryForm", "form-default.ftl"),
SEARCH("getCustomSearchView", "view-search-default.ftl"),
SHORT("getCustomShortView", "view-short-default.ftl");
private Method method = null;
private String path = null;
private String defaultTemplate = null;
ClassView(String methodName, String path) {
ClassView(String methodName, String defaultTemplate) {
Class<VClass> vc = VClass.class;
this.path = path;
this.defaultTemplate = defaultTemplate;
try {
method = vc.getMethod(methodName);
} catch (SecurityException e) {
@ -53,9 +55,9 @@ public class ViewFinder {
return method;
}
protected String getPath() {
return TEMPLATE_PATH + path;
}
protected String getDefaultTemplate() {
return defaultTemplate;
}
}
@ -65,10 +67,11 @@ public class ViewFinder {
this.view = view;
}
public String findClassView(Individual individual, ServletContext context) {
String viewName = "default.ftl";
List<VClass> vclasses = individual.getVClasses();
public String findClassView(Individual individual, ServletContext context, VitroRequest vreq) {
String templateName = view.getDefaultTemplate();
Method method = view.getMethod();
TemplateLoader templateLoader = ((Configuration) vreq.getAttribute("freemarkerConfig")).getTemplateLoader();
/* RY The logic here is incorrect. The vclasses are
* returned in a random order, whereas we need to
* traverse the class hierarchy and find the most
@ -87,27 +90,56 @@ public class ViewFinder {
* RY 7/19/10 Use distinction between asserted and inferred vclasses
* as a starting point: see MiscWebUtils.getCustomShortView().
*/
List<VClass> vclasses = individual.getVClasses();
String customTemplate = null;
for (VClass vc : vclasses) {
try {
String v = (String) method.invoke(vc);
if (!StringUtils.isEmpty(v)) {
String pathToView = context.getRealPath(view.getPath() + "-" + v);
File viewFile = new File(pathToView);
if (viewFile.isFile() && viewFile.canRead()) {
viewName = v;
break;
}
}
} catch (IllegalArgumentException e) {
log.error("Incorrect arguments passed to method " + method.getName() + " in findView().");
} catch (IllegalAccessException e) {
log.error("Method " + method.getName() + " cannot be accessed in findView().");
} catch (InvocationTargetException e) {
log.error("Exception thrown by method " + method.getName() + " in findView().");
customTemplate = findCustomTemplateForVClass(vc, method, templateLoader);
if (customTemplate != null) {
templateName = customTemplate;
break;
}
}
return viewName;
log.debug("Using template " + templateName + " for individual " + individual.getName());
return templateName;
}
private String findCustomTemplateForVClass(VClass vclass, Method method, TemplateLoader templateLoader) {
String customTemplate = null;
String vClassCustomTemplate = null;
try {
vClassCustomTemplate = (String) method.invoke(vclass);
} catch (IllegalArgumentException e) {
log.error("Incorrect arguments passed to method " + method.getName() + " in findCustomTemplateForVClass().");
} catch (IllegalAccessException e) {
log.error("Method " + method.getName() + " cannot be accessed in findCustomTemplateForVClass().");
} catch (InvocationTargetException e) {
log.error("Exception thrown by method " + method.getName() + " in findCustomTemplateForVClass().");
}
if (!StringUtils.isEmpty(vClassCustomTemplate)) {
log.debug("Custom template " + vClassCustomTemplate + " defined for class " + vclass.getName());
try {
// Make sure the template exists
if (templateLoader.findTemplateSource(vClassCustomTemplate) != null) {
log.debug("Found defined custom template " + vClassCustomTemplate + " for class " + vclass.getName());
customTemplate = vClassCustomTemplate;
} else {
log.warn("Custom template " + vClassCustomTemplate + " for class " + vclass.getName() + " defined but does not exist.");
}
} catch (IOException e) {
log.error("IOException looking for source for template " + vClassCustomTemplate);
}
}
if (log.isDebugEnabled()) {
if (customTemplate != null) {
log.debug("Using custom template " + customTemplate + " for class " + vclass.getName());
} else {
log.debug("No custom template found for class " + vclass.getName());
}
}
return customTemplate;
}
}

View file

@ -7,6 +7,7 @@ import javax.servlet.ServletContext;
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.controller.freemarker.UrlBuilder;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder.Params;
@ -15,6 +16,7 @@ public abstract class BaseTemplateModel {
private static final Log log = LogFactory.getLog(BaseTemplateModel.class.getName());
protected static ServletContext servletContext = null;
protected static VitroRequest vreq = null;
// Wrap UrlBuilder method so templates can call ${item.url}
public String getUrl(String path) {
@ -31,28 +33,19 @@ public abstract class BaseTemplateModel {
}
public static void setServletContext(ServletContext context) {
BaseTemplateModel.servletContext = context;
servletContext = context;
}
public static VitroRequest getVitroRequest() {
return vreq;
}
public static void setVitroRequest(VitroRequest vrequest) {
vreq = vrequest;
}
public String dump() {
return "I'm a BaseTemplateModel object";
}
/*
* public static List<?> wrapList(List<?> list, Class cl)
* throw error if cl not a child of ViewObject
* This block of code is going to be repeated a lot:
List<VClassGroup> groups = // code to get the data
List<VClassGroupView> vcgroups = new ArrayList<VClassGroupView>(groups.size());
Iterator<VClassGroup> i = groups.iterator();
while (i.hasNext()) {
vcgroups.add(new VClassGroupView(i.next()));
}
body.put("classGroups", vcgroups);
Can we generalize it to a generic method of ViewObject - wrapList() ?
static method of ViewObject
Params: groups, VClassGroupView (the name of the class) - but must be a child of ViewObject
Return: List<viewObjectType>
*/
}

View file

@ -58,7 +58,7 @@ public class IndividualTemplateModel extends BaseTemplateModel {
private String getView(ClassView view) {
ViewFinder vf = new ViewFinder(view);
return vf.findClassView(individual, servletContext);
return vf.findClassView(individual, servletContext, vreq);
}
public Link getPrimaryLink() {