Rewrote IndividualListController to handle error conditions from within FreeMarker. Reorganized controller control flow to account for interdependencies between body and title.
This commit is contained in:
parent
f40e2d1af7
commit
fbdba79833
11 changed files with 307 additions and 280 deletions
|
@ -2,7 +2,9 @@
|
||||||
|
|
||||||
package edu.cornell.mannlib.vitro.webapp.controller.freemarker;
|
package edu.cornell.mannlib.vitro.webapp.controller.freemarker;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
|
@ -24,6 +26,13 @@ public class AboutController extends FreeMarkerHttpServlet {
|
||||||
body.put("aboutText", portal.getAboutText());
|
body.put("aboutText", portal.getAboutText());
|
||||||
body.put("acknowledgeText", portal.getAcknowledgeText());
|
body.put("acknowledgeText", portal.getAcknowledgeText());
|
||||||
|
|
||||||
|
// Test of #list directive in template on undefined, null, or empty values
|
||||||
|
// Basic idea: empty list okay, null or undefined value not okay
|
||||||
|
// List<String> apples = new ArrayList<String>(); // no error
|
||||||
|
// List<String> apples = null; // error
|
||||||
|
// body.put("apples", apples);
|
||||||
|
// no apples in body: error
|
||||||
|
|
||||||
String bodyTemplate = "about.ftl";
|
String bodyTemplate = "about.ftl";
|
||||||
return mergeBodyToTemplate(bodyTemplate, body);
|
return mergeBodyToTemplate(bodyTemplate, body);
|
||||||
|
|
||||||
|
|
|
@ -18,12 +18,11 @@ import edu.cornell.mannlib.vitro.webapp.dao.filtering.filters.VitroFilterUtils;
|
||||||
import edu.cornell.mannlib.vitro.webapp.dao.filtering.filters.VitroFilters;
|
import edu.cornell.mannlib.vitro.webapp.dao.filtering.filters.VitroFilters;
|
||||||
import edu.cornell.mannlib.vitro.webapp.flags.PortalFlag;
|
import edu.cornell.mannlib.vitro.webapp.flags.PortalFlag;
|
||||||
import edu.cornell.mannlib.vitro.webapp.view.VClassGroupView;
|
import edu.cornell.mannlib.vitro.webapp.view.VClassGroupView;
|
||||||
|
import freemarker.template.SimpleSequence;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
import freemarker.template.*;
|
|
||||||
|
|
||||||
import javax.servlet.ServletContext;
|
import javax.servlet.ServletContext;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
@ -69,7 +68,9 @@ public class BrowseController extends FreeMarkerHttpServlet {
|
||||||
|
|
||||||
protected String getBody() {
|
protected String getBody() {
|
||||||
|
|
||||||
Map body = new HashMap();
|
Map<String, Object> body = new HashMap<String, Object>();
|
||||||
|
String bodyTemplate = "classGroups.ftl";
|
||||||
|
String message = null;
|
||||||
|
|
||||||
// Set main page template attributes specific to this page
|
// Set main page template attributes specific to this page
|
||||||
// But the template should control this! Try putting in a div inside the content.
|
// But the template should control this! Try putting in a div inside the content.
|
||||||
|
@ -80,22 +81,25 @@ public class BrowseController extends FreeMarkerHttpServlet {
|
||||||
|
|
||||||
//PortalFlag portalState= vreq.getPortalFlag();
|
//PortalFlag portalState= vreq.getPortalFlag();
|
||||||
|
|
||||||
String message = "";
|
List<VClassGroup> groups = getGroups(vreq.getWebappDaoFactory().getVClassGroupDao(), portalId);
|
||||||
List<VClassGroup> groups = getGroups(vreq.getWebappDaoFactory().getVClassGroupDao(), vreq.getPortal().getPortalId());
|
|
||||||
if (groups == null || groups.isEmpty()) {
|
if (groups == null || groups.isEmpty()) {
|
||||||
message = "There are not yet any items in the system.";
|
message = "There are not yet any items in the system.";
|
||||||
body.put("message", message);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
// FreeMarker will wrap vcgroups in a SimpleSequence. So do we want to create the SimpleSequence directly?
|
||||||
|
// But, makes code less portable to another system.
|
||||||
|
// SimpleSequence vcgroups = new SimpleSequence(groups.size());
|
||||||
List<VClassGroupView> vcgroups = new ArrayList<VClassGroupView>(groups.size());
|
List<VClassGroupView> vcgroups = new ArrayList<VClassGroupView>(groups.size());
|
||||||
Iterator<VClassGroup> i = groups.iterator();
|
for (VClassGroup g: groups) {
|
||||||
while (i.hasNext()) {
|
vcgroups.add(new VClassGroupView(g));
|
||||||
vcgroups.add(new VClassGroupView(i.next()));
|
|
||||||
}
|
}
|
||||||
body.put("classGroups", vcgroups);
|
body.put("classGroups", vcgroups);
|
||||||
}
|
}
|
||||||
|
|
||||||
String bodyTemplate = "classGroups.ftl";
|
if (message != null) {
|
||||||
|
body.put("message", message);
|
||||||
|
}
|
||||||
|
|
||||||
return mergeBodyToTemplate(bodyTemplate, body);
|
return mergeBodyToTemplate(bodyTemplate, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -66,17 +66,12 @@ public class FreeMarkerHttpServlet extends VitroHttpServlet {
|
||||||
protected String appName;
|
protected String appName;
|
||||||
protected Map<String, Object> root = new HashMap<String, Object>();
|
protected Map<String, Object> root = new HashMap<String, Object>();
|
||||||
|
|
||||||
// Some servlets have their own doGet() method, in which case they need to call
|
|
||||||
// doSetup(), setTitle(), setBody(), and write() themselves. Other servlets define only
|
|
||||||
// a getBody() and getTitle() method and use the parent doGet() method.
|
|
||||||
public void doGet( HttpServletRequest request, HttpServletResponse response )
|
public void doGet( HttpServletRequest request, HttpServletResponse response )
|
||||||
throws IOException, ServletException {
|
throws IOException, ServletException {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
callSuperGet(request, response); // ??
|
|
||||||
doSetup(request, response);
|
doSetup(request, response);
|
||||||
setTitle();
|
setTitleAndBody();
|
||||||
setBody();
|
|
||||||
write(response);
|
write(response);
|
||||||
|
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
|
@ -91,88 +86,21 @@ public class FreeMarkerHttpServlet extends VitroHttpServlet {
|
||||||
doGet(request, response);
|
doGet(request, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setBody() {
|
// Basic setup needed by all controllers
|
||||||
root.put("body", getBody());
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void setSharedVariable(String key, Object value) {
|
|
||||||
try {
|
|
||||||
config.setSharedVariable(key, value);
|
|
||||||
} catch (TemplateModelException e) {
|
|
||||||
log.error("Can't set shared variable '" + key + "'.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void setTitle() {
|
|
||||||
setSharedVariable("title", getTitle());
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String getTitle() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String getBody() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected StringWriter mergeToTemplate(String templateName, Map<String, Object> map) {
|
|
||||||
|
|
||||||
Template template = null;
|
|
||||||
try {
|
|
||||||
template = config.getTemplate(templateName);
|
|
||||||
} catch (IOException e) {
|
|
||||||
log.error("Cannot get template " + templateName);
|
|
||||||
}
|
|
||||||
StringWriter sw = new StringWriter();
|
|
||||||
if (template != null) {
|
|
||||||
try {
|
|
||||||
template.process(map, sw);
|
|
||||||
} catch (TemplateException e) {
|
|
||||||
// TODO Auto-generated catch block
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (IOException e) {
|
|
||||||
// TODO Auto-generated catch block
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return sw;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String mergeBodyToTemplate(String templateName, Map<String, Object> map) {
|
|
||||||
templateName = "body/" + templateName;
|
|
||||||
String body = mergeToTemplate(templateName, map).toString();
|
|
||||||
return body;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void write(HttpServletResponse response) {
|
|
||||||
|
|
||||||
String templateName = "page/default.ftl";
|
|
||||||
StringWriter sw = mergeToTemplate(templateName, root);
|
|
||||||
try {
|
|
||||||
PrintWriter out = response.getWriter();
|
|
||||||
out.print(sw);
|
|
||||||
} catch (IOException e) {
|
|
||||||
// TODO Auto-generated catch block
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void callSuperGet(HttpServletRequest request, HttpServletResponse response) {
|
|
||||||
try {
|
|
||||||
super.doGet(request,response);
|
|
||||||
} catch (ServletException e) {
|
|
||||||
// TODO Auto-generated catch block
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (IOException e) {
|
|
||||||
// TODO Auto-generated catch block
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// RY This needs to be broken out as is for FreeMarkerComponentGenerator, which should not
|
|
||||||
// include callSuperGet(). So it's only temporary.
|
|
||||||
protected void doSetup(HttpServletRequest request, HttpServletResponse response) {
|
protected void doSetup(HttpServletRequest request, HttpServletResponse response) {
|
||||||
|
|
||||||
|
if ( !(this instanceof FreeMarkerComponentGenerator) ) {
|
||||||
|
try {
|
||||||
|
super.doGet(request,response);
|
||||||
|
} catch (ServletException e) {
|
||||||
|
log.error("Servlet exception calling VitroHttpRequest.doGet()");
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("IO exception calling VitroHttpRequest.doGet()");
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
vreq = new VitroRequest(request);
|
vreq = new VitroRequest(request);
|
||||||
this.response = response;
|
this.response = response;
|
||||||
portal = vreq.getPortal();
|
portal = vreq.getPortal();
|
||||||
|
@ -211,6 +139,34 @@ public class FreeMarkerHttpServlet extends VitroHttpServlet {
|
||||||
setSharedVariable("scripts", new ScriptList());
|
setSharedVariable("scripts", new ScriptList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Define template locations. Template loader will look first in the theme-specific
|
||||||
|
// location, then in the vitro location.
|
||||||
|
// RY We cannot do this in FreeMarkerSetup because (a) the theme depends on the portal,
|
||||||
|
// and we have multi-portal installations, and (b) we need to support theme-switching on the fly.
|
||||||
|
// To make more efficient, we could do this once, and then have a listener that does it again
|
||||||
|
// when theme is switched. BUT this doesn't support (a), only (b), so we have to do it on every request.
|
||||||
|
protected final void setTemplateLoader() {
|
||||||
|
|
||||||
|
String themeTemplateDir = context.getRealPath(getThemeDir()) + "/ftl";
|
||||||
|
String vitroTemplateDir = context.getRealPath("/templates/freemarker");
|
||||||
|
|
||||||
|
try {
|
||||||
|
FileTemplateLoader themeFtl = new FileTemplateLoader(new File(themeTemplateDir));
|
||||||
|
FileTemplateLoader vitroFtl = new FileTemplateLoader(new File(vitroTemplateDir));
|
||||||
|
ClassTemplateLoader ctl = new ClassTemplateLoader(getClass(), "");
|
||||||
|
TemplateLoader[] loaders = new TemplateLoader[] { themeFtl, vitroFtl, ctl };
|
||||||
|
MultiTemplateLoader mtl = new MultiTemplateLoader(loaders);
|
||||||
|
config.setTemplateLoader(mtl);
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("Error loading templates");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private TabMenu getTabMenu() {
|
||||||
|
return new TabMenu(vreq, portalId);
|
||||||
|
}
|
||||||
|
|
||||||
public String getThemeDir() {
|
public String getThemeDir() {
|
||||||
return portal.getThemeDir().replaceAll("/$", "");
|
return portal.getThemeDir().replaceAll("/$", "");
|
||||||
}
|
}
|
||||||
|
@ -252,31 +208,31 @@ public class FreeMarkerHttpServlet extends VitroHttpServlet {
|
||||||
setSharedVariable("urls", urls);
|
setSharedVariable("urls", urls);
|
||||||
}
|
}
|
||||||
|
|
||||||
private final void setLoginInfo() {
|
private final void setLoginInfo() {
|
||||||
|
|
||||||
String loginName = null;
|
String loginName = null;
|
||||||
int securityLevel;
|
int securityLevel;
|
||||||
|
|
||||||
HttpSession session = vreq.getSession();
|
HttpSession session = vreq.getSession();
|
||||||
LoginFormBean loginBean = (LoginFormBean) session.getAttribute("loginHandler");
|
LoginFormBean loginBean = (LoginFormBean) session.getAttribute("loginHandler");
|
||||||
if (loginBean != null && loginBean.testSessionLevel(vreq) > -1) {
|
if (loginBean != null && loginBean.testSessionLevel(vreq) > -1) {
|
||||||
loginName = loginBean.getLoginName();
|
loginName = loginBean.getLoginName();
|
||||||
securityLevel = Integer.parseInt(loginBean.getLoginRole());
|
securityLevel = Integer.parseInt(loginBean.getLoginRole());
|
||||||
}
|
}
|
||||||
if (loginName != null) {
|
if (loginName != null) {
|
||||||
root.put("loginName", loginName);
|
root.put("loginName", loginName);
|
||||||
|
|
||||||
securityLevel = Integer.parseInt(loginBean.getLoginRole());
|
securityLevel = Integer.parseInt(loginBean.getLoginRole());
|
||||||
if (securityLevel >= FILTER_SECURITY_LEVEL) {
|
if (securityLevel >= FILTER_SECURITY_LEVEL) {
|
||||||
ApplicationBean appBean = vreq.getAppBean();
|
ApplicationBean appBean = vreq.getAppBean();
|
||||||
if (appBean.isFlag1Active()) {
|
if (appBean.isFlag1Active()) {
|
||||||
root.put("showFlag1SearchField", true);
|
root.put("showFlag1SearchField", true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final void setCopyrightInfo() {
|
private final void setCopyrightInfo() {
|
||||||
|
|
||||||
String copyrightText = portal.getCopyrightAnchor();
|
String copyrightText = portal.getCopyrightAnchor();
|
||||||
if ( ! StringUtils.isEmpty(copyrightText) ) {
|
if ( ! StringUtils.isEmpty(copyrightText) ) {
|
||||||
|
@ -289,13 +245,13 @@ public class FreeMarkerHttpServlet extends VitroHttpServlet {
|
||||||
copyright.put("url", portal.getCopyrightURL());
|
copyright.put("url", portal.getCopyrightURL());
|
||||||
root.put("copyright", copyright);
|
root.put("copyright", copyright);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final void setThemeInfo(String themeDir) {
|
private final void setThemeInfo(String themeDir) {
|
||||||
|
|
||||||
// This value will be available to any template as a path for adding a new stylesheet.
|
// This value will be available to any template as a path for adding a new stylesheet.
|
||||||
// It does not contain the context path, because the methods to generate the href
|
// It does not contain the context path, because the methods to generate the href
|
||||||
// attribute from the string passed in by the template automatically add the context path.
|
// attribute from the string passed in by the template automatically add the context path.
|
||||||
setSharedVariable("stylesheetDir", themeDir + "/css");
|
setSharedVariable("stylesheetDir", themeDir + "/css");
|
||||||
|
|
||||||
String themeDirWithContext = getUrl(themeDir);
|
String themeDirWithContext = getUrl(themeDir);
|
||||||
|
@ -305,41 +261,107 @@ public class FreeMarkerHttpServlet extends VitroHttpServlet {
|
||||||
|
|
||||||
setSharedVariable("siteIconPath", themeDirWithContext + "/site_icons");
|
setSharedVariable("siteIconPath", themeDirWithContext + "/site_icons");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default case is to set title first, because it's used in the body. However, in some cases
|
||||||
|
// the title is based on values computed during compilation of the body (e.g., IndividualListController).
|
||||||
|
// Individual controllers can override this method to set title and body together. End result must be:
|
||||||
|
// body is added to root with key "body"
|
||||||
|
// title is set as a shared variable with key "title"
|
||||||
|
// This can be achieved by making sure setBody() and setTitle() are called.
|
||||||
|
protected void setTitleAndBody() {
|
||||||
|
setTitle();
|
||||||
|
setBody();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setBody() {
|
||||||
|
root.put("body", getBody());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Define template locations. Template loader will look first in the theme-specific
|
protected String getBody() {
|
||||||
// location, then in the vitro location.
|
return ""; // body should never be null
|
||||||
// RY We cannot do this in FreeMarkerSetup because (a) the theme depends on the portal,
|
}
|
||||||
// and we have multi-portal installations, and (b) we need to support theme-switching on the fly.
|
|
||||||
// To make more efficient, we could do this once, and then have a listener that does it again
|
|
||||||
// when theme is switched. BUT this doesn't support (a), only (b), so we have to do it on every request.
|
|
||||||
protected final void setTemplateLoader() {
|
|
||||||
|
|
||||||
String themeTemplateDir = context.getRealPath(getThemeDir()) + "/ftl";
|
protected void setTitle() {
|
||||||
String vitroTemplateDir = context.getRealPath("/templates/freemarker");
|
String title = getTitle();
|
||||||
|
// If the individual controller fails to assign a non-null, non-empty title
|
||||||
|
if (StringUtils.isEmpty(title)) {
|
||||||
|
title = appName;
|
||||||
|
}
|
||||||
|
// Title is a shared variable because it's used in both body and head elements.
|
||||||
|
setSharedVariable("title", title);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String getTitle() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setSharedVariable(String key, Object value) {
|
||||||
try {
|
try {
|
||||||
FileTemplateLoader themeFtl = new FileTemplateLoader(new File(themeTemplateDir));
|
config.setSharedVariable(key, value);
|
||||||
FileTemplateLoader vitroFtl = new FileTemplateLoader(new File(vitroTemplateDir));
|
} catch (TemplateModelException e) {
|
||||||
ClassTemplateLoader ctl = new ClassTemplateLoader(getClass(), "");
|
log.error("Can't set shared variable '" + key + "'.");
|
||||||
TemplateLoader[] loaders = new TemplateLoader[] { themeFtl, vitroFtl, ctl };
|
|
||||||
MultiTemplateLoader mtl = new MultiTemplateLoader(loaders);
|
|
||||||
config.setTemplateLoader(mtl);
|
|
||||||
} catch (IOException e) {
|
|
||||||
log.error("Error loading templates");
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
protected StringWriter mergeToTemplate(String templateName, Map<String, Object> map) {
|
||||||
|
|
||||||
private TabMenu getTabMenu() {
|
Template template = null;
|
||||||
return new TabMenu(vreq, portalId);
|
try {
|
||||||
}
|
template = config.getTemplate(templateName);
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("Cannot get template " + templateName);
|
||||||
|
}
|
||||||
|
StringWriter sw = new StringWriter();
|
||||||
|
if (template != null) {
|
||||||
|
try {
|
||||||
|
template.process(map, sw);
|
||||||
|
} catch (TemplateException e) {
|
||||||
|
// TODO Auto-generated catch block
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (IOException e) {
|
||||||
|
// TODO Auto-generated catch block
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sw;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String mergeBodyToTemplate(String templateName, Map<String, Object> map) {
|
||||||
|
templateName = "body/" + templateName;
|
||||||
|
String body = mergeToTemplate(templateName, map).toString();
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void write(HttpServletResponse response) {
|
||||||
|
|
||||||
|
String templateName = "page/" + getPageTemplateName();
|
||||||
|
|
||||||
|
StringWriter sw = mergeToTemplate(templateName, root);
|
||||||
|
try {
|
||||||
|
PrintWriter out = response.getWriter();
|
||||||
|
out.print(sw);
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("FreeMarkerHttpServlet cannot write output");
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Can be overridden by individual controllers
|
||||||
|
protected String getPageTemplateName() {
|
||||||
|
return "default.ftl";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static boolean isConfigured() {
|
||||||
|
return config != null;
|
||||||
|
}
|
||||||
|
|
||||||
// TEMPORARY for transition from JSP to FreeMarker. Once transition
|
// TEMPORARY for transition from JSP to FreeMarker. Once transition
|
||||||
// is complete and no more pages are generated in JSP, this can be removed.
|
// is complete and no more pages are generated in JSP, this can be removed.
|
||||||
// Do this if FreeMarker is configured (i.e., not Datastar) and if we are not in
|
// Do this if FreeMarker is configured (i.e., not Datastar) and if we are not in
|
||||||
// a FreeMarkerHttpServlet, which will generate identity, menu, and footer from the page template.
|
// a FreeMarkerHttpServlet, which will generate identity, menu, and footer from the page template.
|
||||||
// It's a static method because it needs to be called from JSPs that don't go through a servlet.
|
// It's a static method because it needs to be called from JSPs that don't go through a servlet.
|
||||||
public static void getFreeMarkerComponentsForJsp(HttpServletRequest request, HttpServletResponse response) {
|
public static void getFreeMarkerComponentsForJsp(HttpServletRequest request, HttpServletResponse response) {
|
||||||
FreeMarkerComponentGenerator fcg = new FreeMarkerComponentGenerator(request, response);
|
FreeMarkerComponentGenerator fcg = new FreeMarkerComponentGenerator(request, response);
|
||||||
request.setAttribute("ftl_identity", fcg.getIdentity());
|
request.setAttribute("ftl_identity", fcg.getIdentity());
|
||||||
|
@ -348,11 +370,7 @@ public class FreeMarkerHttpServlet extends VitroHttpServlet {
|
||||||
request.setAttribute("ftl_footer", fcg.getFooter());
|
request.setAttribute("ftl_footer", fcg.getFooter());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isConfigured() {
|
/* ******************** Static utilities ******************* */
|
||||||
return config != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ******************** Utilities ******************* */
|
|
||||||
|
|
||||||
public static String getUrl(String path) {
|
public static String getUrl(String path) {
|
||||||
if ( ! path.startsWith("/") ) {
|
if ( ! path.startsWith("/") ) {
|
||||||
|
|
|
@ -2,144 +2,119 @@
|
||||||
|
|
||||||
package edu.cornell.mannlib.vitro.webapp.controller.freemarker;
|
package edu.cornell.mannlib.vitro.webapp.controller.freemarker;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.servlet.RequestDispatcher;
|
|
||||||
import javax.servlet.ServletException;
|
|
||||||
import javax.servlet.ServletOutputStream;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
import edu.cornell.mannlib.vitro.webapp.beans.Individual;
|
import edu.cornell.mannlib.vitro.webapp.beans.Individual;
|
||||||
import edu.cornell.mannlib.vitro.webapp.beans.VClass;
|
import edu.cornell.mannlib.vitro.webapp.beans.VClass;
|
||||||
import edu.cornell.mannlib.vitro.webapp.beans.VClassGroup;
|
import edu.cornell.mannlib.vitro.webapp.beans.VClassGroup;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.utils.StringUtils;
|
||||||
import edu.cornell.mannlib.vitro.webapp.view.IndividualView;
|
import edu.cornell.mannlib.vitro.webapp.view.IndividualView;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a list of individuals for display in a template
|
||||||
|
*/
|
||||||
public class IndividualListController extends FreeMarkerHttpServlet {
|
public class IndividualListController extends FreeMarkerHttpServlet {
|
||||||
|
|
||||||
long startTime = -1;
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
private static final Log log = LogFactory.getLog(IndividualListController.class.getName());
|
private static final Log log = LogFactory.getLog(IndividualListController.class.getName());
|
||||||
private VClass vclass = null;
|
private VClass vclass = null;
|
||||||
|
private String title = null;
|
||||||
|
|
||||||
/**
|
protected void setTitleAndBody() {
|
||||||
* This generates a list of entities and then sends that
|
setBody();
|
||||||
* off to a jsp to be displayed.
|
}
|
||||||
*
|
|
||||||
* Expected parameters:
|
protected String getBody() {
|
||||||
*
|
|
||||||
* Expected Attributes:
|
Map<String, Object> body = new HashMap<String, Object>();
|
||||||
* entity - set to entity to display properties for.
|
String bodyTemplate = "individualList.ftl";
|
||||||
*
|
String errorMessage = null;
|
||||||
* @author bdc34
|
String message = null;
|
||||||
*/
|
|
||||||
|
|
||||||
// TODO Rewrite error cases to use FreeMarker templates. Restructure so we're always doing the body
|
|
||||||
// and then calling writeOutput().
|
|
||||||
public void doGet( HttpServletRequest req, HttpServletResponse res )
|
|
||||||
throws IOException, ServletException {
|
|
||||||
startTime = System.currentTimeMillis(); // TODO: remove
|
|
||||||
try {
|
try {
|
||||||
super.doSetup(req, res);
|
|
||||||
Object obj = vreq.getAttribute("vclass");
|
Object obj = vreq.getAttribute("vclass");
|
||||||
vclass=null;
|
vclass = null;
|
||||||
if( obj == null ) { // look for vitroclass id parameter
|
if ( obj == null ) { // look for vitroclass id parameter
|
||||||
String vitroClassIdStr=req.getParameter("vclassId");
|
String vitroClassIdStr = vreq.getParameter("vclassId");
|
||||||
if (vitroClassIdStr!=null && !vitroClassIdStr.equals("")) {
|
if ( !StringUtils.isEmpty(vitroClassIdStr)) {
|
||||||
try {
|
try {
|
||||||
//TODO have to change this so vclass's group and entity count are populated
|
//TODO have to change this so vclass's group and entity count are populated
|
||||||
vclass = vreq.getWebappDaoFactory().getVClassDao().getVClassByURI(vitroClassIdStr);
|
vclass = vreq.getWebappDaoFactory().getVClassDao().getVClassByURI(vitroClassIdStr);
|
||||||
if (vclass == null) {
|
if (vclass == null) {
|
||||||
log.error("Couldn't retrieve vclass "+vitroClassIdStr);
|
log.error("Couldn't retrieve vclass " + vitroClassIdStr);
|
||||||
response.sendRedirect(Routes.BROWSE + "?"+vreq.getQueryString());
|
errorMessage = "Class " + vitroClassIdStr + " not found";
|
||||||
}
|
}
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
throw new HelpException("IndividualListController: request parameter 'vclassId' must be a URI string");
|
throw new HelpException("IndividualListController: request parameter 'vclassId' must be a URI string.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (obj instanceof VClass) {
|
} else if (obj instanceof VClass) {
|
||||||
vclass = (VClass)obj;
|
vclass = (VClass)obj;
|
||||||
} else {
|
} else {
|
||||||
throw new HelpException("IndividualListController: attribute 'vclass' must be of type "
|
throw new HelpException("IndividualListController: attribute 'vclass' must be of type "
|
||||||
+ VClass.class.getName() );
|
+ VClass.class.getName() + ".");
|
||||||
}
|
}
|
||||||
if (vclass!=null){
|
|
||||||
setBody();
|
if (vclass != null) {
|
||||||
write(response);
|
// Create list of individual view objects
|
||||||
|
List<Individual> individualList = vreq.getWebappDaoFactory().getIndividualDao().getIndividualsByVClass(vclass);
|
||||||
|
List<IndividualView> individuals = new ArrayList<IndividualView>(individualList.size());
|
||||||
|
|
||||||
|
if (individualList == null) {
|
||||||
|
// RY Is this really an error?
|
||||||
|
log.error("individuals list is null");
|
||||||
|
message = "No individuals to display.";
|
||||||
|
} else {
|
||||||
|
for (Individual i: individualList) {
|
||||||
|
individuals.add(new IndividualView(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set title and subtitle. Title will be retrieved later in getTitle().
|
||||||
|
VClassGroup classGroup = vclass.getGroup();
|
||||||
|
if (classGroup == null) {
|
||||||
|
title = vclass.getName();
|
||||||
|
} else {
|
||||||
|
title = classGroup.getPublicName();
|
||||||
|
body.put("subtitle", vclass.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
body.put("individuals", individuals);
|
||||||
}
|
}
|
||||||
// RY Rewrite error cases for FreeMarker, not JSP
|
|
||||||
} catch (HelpException help){
|
} catch (HelpException help){
|
||||||
doHelp(response);
|
errorMessage = "Request attribute 'vclass' or request parameter 'vclassId' must be set before calling. Its value must be a class uri.";
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
vreq.setAttribute("javax.servlet.jsp.jspException",e);
|
bodyTemplate = "error.ftl";
|
||||||
RequestDispatcher rd = req.getRequestDispatcher("/error.jsp");
|
|
||||||
rd.forward(vreq, response);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void doPost(HttpServletRequest request, HttpServletResponse response)
|
|
||||||
throws ServletException,IOException {
|
|
||||||
doGet(request, response);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String getBody() {
|
|
||||||
|
|
||||||
Map<String, Object> body = new HashMap<String, Object>();
|
|
||||||
|
|
||||||
// Create list of individuals
|
|
||||||
List<Individual> individualList = vreq.getWebappDaoFactory().getIndividualDao().getIndividualsByVClass(vclass);
|
|
||||||
List<IndividualView> individuals = new ArrayList<IndividualView>(individualList.size());
|
|
||||||
Iterator<Individual> i = individualList.iterator();
|
|
||||||
while (i.hasNext()) {
|
|
||||||
individuals.add(new IndividualView(i.next()));
|
|
||||||
}
|
|
||||||
body.put("individuals", individuals);
|
|
||||||
|
|
||||||
// But the JSP version includes url rewriting via URLRewritingHttpServletResponse
|
|
||||||
// RY *** FIX - define getUrl method of IndividualView
|
|
||||||
body.put("individualUrl", getUrl("/entity?home=" + portalId + "&uri="));
|
|
||||||
|
|
||||||
if (individuals == null) {
|
|
||||||
log.error("individuals list is null");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use instead of getTitle(), because we have a subtitle too
|
if (errorMessage != null) {
|
||||||
String title = "";
|
bodyTemplate = "errorMessage.ftl";
|
||||||
VClassGroup classGroup=vclass.getGroup();
|
body.put("errorMessage", errorMessage);
|
||||||
if (classGroup==null) {
|
} else if (message != null) {
|
||||||
title = vclass.getName();
|
body.put("message", message);
|
||||||
} else {
|
|
||||||
title = classGroup.getPublicName();
|
|
||||||
setSharedVariable("subTitle", vclass.getName());
|
|
||||||
}
|
}
|
||||||
setSharedVariable("title", title);
|
|
||||||
|
|
||||||
String templateName = "individualList.ftl";
|
setTitle();
|
||||||
return mergeBodyToTemplate(templateName, body);
|
|
||||||
|
|
||||||
|
return mergeBodyToTemplate(bodyTemplate, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
// RY Rewrite as a template
|
protected String getTitle() {
|
||||||
private void doHelp(HttpServletResponse res)
|
// The title is determined during compilation of the body, so we put it in an instance variable
|
||||||
throws IOException, ServletException {
|
// to be retrieved later.
|
||||||
ServletOutputStream out = res.getOutputStream();
|
return title;
|
||||||
res.setContentType("text/html; charset=UTF-8");
|
|
||||||
out.println("<html><body><h2>Quick Notes on using EntityList:</h2>");
|
|
||||||
out.println("<p>request.attributes 'entities' must be set by servlet before calling."
|
|
||||||
+" It must be a List of Entity objects </p>");
|
|
||||||
out.println("</body></html>");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class HelpException extends Throwable{
|
private class HelpException extends Throwable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
public HelpException(String string) {
|
public HelpException(String string) {
|
||||||
super(string);
|
super(string);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ public class Routes {
|
||||||
public static final String BROWSE = "/browse";
|
public static final String BROWSE = "/browse";
|
||||||
public static final String COMMENT_FORM = "/comments";
|
public static final String COMMENT_FORM = "/comments";
|
||||||
public static final String INDIVIDUAL = "/individual";
|
public static final String INDIVIDUAL = "/individual";
|
||||||
public static final String INDIVIDUAL_LIST = "/entitylist"; // "/individuallist";
|
public static final String INDIVIDUAL_LIST = "/individuallist"; // "/entitylist"; "/individuallist";
|
||||||
public static final String SEARCH = "/search";
|
public static final String SEARCH = "/search";
|
||||||
public static final String TERMS_OF_USE = "/termsOfUse";
|
public static final String TERMS_OF_USE = "/termsOfUse";
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,8 @@ public class IndividualView extends ViewObject {
|
||||||
return individual.getName();
|
return individual.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RY However, the moniker should undergo p:process but the class name shouldn't!
|
||||||
|
// So, it needs to be callable from Java.
|
||||||
public String getTagline() {
|
public String getTagline() {
|
||||||
String tagline = individual.getMoniker();
|
String tagline = individual.getMoniker();
|
||||||
return StringUtils.isEmpty(tagline) ? individual.getVClass().getName() : tagline;
|
return StringUtils.isEmpty(tagline) ? individual.getVClass().getName() : tagline;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
|
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
|
||||||
|
|
||||||
<#-- Comment form -->
|
<#-- Contact form -->
|
||||||
|
|
||||||
<div class="staticPageBackground feedbackForm">
|
<div class="staticPageBackground feedbackForm">
|
||||||
|
|
||||||
|
|
7
webapp/web/templates/freemarker/body/error.ftl
Normal file
7
webapp/web/templates/freemarker/body/error.ftl
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
|
||||||
|
|
||||||
|
<#-- Template for general system error. -->
|
||||||
|
|
||||||
|
<p>There was an error in the system.</p>
|
||||||
|
|
||||||
|
<p>Return to the <a href="${urls.home}">home page</a>.</p>
|
7
webapp/web/templates/freemarker/body/errorMessage.ftl
Normal file
7
webapp/web/templates/freemarker/body/errorMessage.ftl
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
|
||||||
|
|
||||||
|
<#-- Standard template to display an error message generated from any controller. Keeps this out of individual templates. -->
|
||||||
|
|
||||||
|
<#if errorMessage??>
|
||||||
|
<p>${errorMessage}</p>
|
||||||
|
</#if>
|
|
@ -7,16 +7,21 @@
|
||||||
<div class="individualList">
|
<div class="individualList">
|
||||||
<h2>${title}</h2>
|
<h2>${title}</h2>
|
||||||
<#if subtitle??>
|
<#if subtitle??>
|
||||||
<h4>${subTitle}"</h4>
|
<h4>${subtitle}</h4>
|
||||||
</#if>
|
</#if>
|
||||||
|
|
||||||
<#-- RY NEED TO ACCOUNT FOR p:process stuff -->
|
<#if message??>
|
||||||
<ul>
|
<p>${message}</p>
|
||||||
<#list individuals as individual>
|
<#else>
|
||||||
<li>
|
<#-- RY NEED TO ACCOUNT FOR p:process stuff -->
|
||||||
<a href="${individual.profileUrl}">${individual.name}</a> ${individual.tagline}
|
<ul>
|
||||||
</li>
|
<#list individuals as individual>
|
||||||
</#list>
|
<li>
|
||||||
</ul>
|
<a href="${individual.profileUrl}">${individual.name}</a> ${individual.tagline}
|
||||||
|
</li>
|
||||||
|
</#list>
|
||||||
|
</ul>
|
||||||
|
</#if>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Add table
Reference in a new issue