NIHVIVO-1304 Rewrote widget framework to support a single template per widget, with multiple macros in each template file.
This commit is contained in:
parent
965f4c399b
commit
8a49574f7e
7 changed files with 88 additions and 63 deletions
|
@ -18,10 +18,11 @@ public class LoginWidget extends Widget {
|
||||||
private static final Log log = LogFactory.getLog(LoginWidget.class);
|
private static final Log log = LogFactory.getLog(LoginWidget.class);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected WidgetTemplateValues process(Environment env, Map params, String widgetName, HttpServletRequest request, ServletContext context) {
|
protected WidgetTemplateValues process(Environment env, Map params,
|
||||||
|
HttpServletRequest request, ServletContext context) {
|
||||||
Map<String, Object> map = new HashMap<String, Object>();
|
Map<String, Object> map = new HashMap<String, Object>();
|
||||||
map.put("fruit", "bananas");
|
map.put("fruit", "bananas");
|
||||||
return new WidgetTemplateValues (getMarkupTemplateName(widgetName), map);
|
return new WidgetTemplateValues (getMarkupMacroName(), map);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,10 +13,11 @@ import freemarker.core.Environment;
|
||||||
public class TestWidget extends Widget {
|
public class TestWidget extends Widget {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected WidgetTemplateValues process(Environment env, Map params, String widgetName, HttpServletRequest request, ServletContext context) {
|
protected WidgetTemplateValues process(Environment env, Map params,
|
||||||
|
HttpServletRequest request, ServletContext context) {
|
||||||
Map<String, Object> map = new HashMap<String, Object>();
|
Map<String, Object> map = new HashMap<String, Object>();
|
||||||
map.put("fruit", "bananas");
|
map.put("fruit", "bananas");
|
||||||
return new WidgetTemplateValues (getMarkupTemplateName(widgetName), map);
|
return new WidgetTemplateValues (getMarkupMacroName(), map);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
package edu.cornell.mannlib.vitro.webapp.web.widgets;
|
package edu.cornell.mannlib.vitro.webapp.web.widgets;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.StringReader;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
@ -14,9 +15,8 @@ import javax.servlet.http.HttpServletRequest;
|
||||||
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.cache.TemplateLoader;
|
|
||||||
import freemarker.core.Environment;
|
import freemarker.core.Environment;
|
||||||
import freemarker.template.Configuration;
|
import freemarker.core.Macro;
|
||||||
import freemarker.template.Template;
|
import freemarker.template.Template;
|
||||||
import freemarker.template.TemplateHashModel;
|
import freemarker.template.TemplateHashModel;
|
||||||
import freemarker.template.TemplateModelException;
|
import freemarker.template.TemplateModelException;
|
||||||
|
@ -31,18 +31,12 @@ public abstract class Widget {
|
||||||
|
|
||||||
public String doAssets(Environment env, Map params) {
|
public String doAssets(Environment env, Map params) {
|
||||||
String widgetName = params.get("name").toString(); //getWidgetName();
|
String widgetName = params.get("name").toString(); //getWidgetName();
|
||||||
String templateName = getAssetsTemplateName(widgetName);
|
Macro assetsMacro = getMacroFromTemplate(getAssetsMacroName(), widgetName, env);
|
||||||
|
|
||||||
// Allow the assets template to be absent without generating an error.
|
|
||||||
TemplateLoader templateLoader = env.getConfiguration().getTemplateLoader();
|
|
||||||
try {
|
|
||||||
if ( templateLoader.findTemplateSource(templateName) == null ) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
log.error("Error finding template source", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Allow there to be no assets macro in the template
|
||||||
|
if (assetsMacro == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
TemplateHashModel dataModel = env.getDataModel();
|
TemplateHashModel dataModel = env.getDataModel();
|
||||||
Map<String, Object> map = new HashMap<String, Object>();
|
Map<String, Object> map = new HashMap<String, Object>();
|
||||||
|
|
||||||
|
@ -54,30 +48,36 @@ public abstract class Widget {
|
||||||
log.error("Error getting asset values from data model.");
|
log.error("Error getting asset values from data model.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return processTemplateToString(widgetName, env, templateName, map);
|
return processMacroToString(env, widgetName, assetsMacro, map);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String doMarkup(Environment env, Map params) {
|
public String doMarkup(Environment env, Map params) {
|
||||||
HttpServletRequest request = (HttpServletRequest) env.getCustomAttribute("request");
|
HttpServletRequest request = (HttpServletRequest) env.getCustomAttribute("request");
|
||||||
ServletContext context = (ServletContext) env.getCustomAttribute("context");
|
ServletContext context = (ServletContext) env.getCustomAttribute("context");
|
||||||
|
|
||||||
|
WidgetTemplateValues values = process(env, params, request, context);
|
||||||
String widgetName = params.get("name").toString(); // getWidgetName();
|
String widgetName = params.get("name").toString(); // getWidgetName();
|
||||||
WidgetTemplateValues values = process(env, params, widgetName, request, context);
|
return processMacroToString(env, widgetName, values);
|
||||||
return processTemplateToString(widgetName, env, values);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default assets template name. Can be overridden by subclasses.
|
// Default template name. Can be overridden by subclasses.
|
||||||
protected String getAssetsTemplateName(String widgetName) {
|
protected String getTemplateName(String widgetName) {
|
||||||
return "widget-" + widgetName + "-assets.ftl";
|
return "widget-" + widgetName + ".ftl";
|
||||||
}
|
|
||||||
|
|
||||||
// Default markup template name. Can be overridden in subclasses, or assigned
|
|
||||||
// differently in the subclass process() method. For example, LoginWidget will
|
|
||||||
// select a template according to login processing status.
|
|
||||||
protected String getMarkupTemplateName(String widgetName) {
|
|
||||||
return "widget-" + widgetName + "-markup.ftl";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Default assets macro name. Can be overridden by subclasses.
|
||||||
|
protected String getAssetsMacroName() {
|
||||||
|
return "assets";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default markup macro name. Can be overridden by subclasses, or
|
||||||
|
// subclass process() method can select from various markup macros
|
||||||
|
// based on widget state. For example, the login widget markup macro will
|
||||||
|
// differ depending on login processing state.
|
||||||
|
protected String getMarkupMacroName() {
|
||||||
|
return "markup";
|
||||||
|
}
|
||||||
|
|
||||||
// private String getWidgetName() {
|
// private String getWidgetName() {
|
||||||
// String name = this.getClass().getName();
|
// String name = this.getClass().getName();
|
||||||
// name= name.replaceAll(".*\\.", "");
|
// name= name.replaceAll(".*\\.", "");
|
||||||
|
@ -86,31 +86,57 @@ public abstract class Widget {
|
||||||
// return name;
|
// return name;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
protected abstract WidgetTemplateValues process(Environment env, Map params, String widgetName, HttpServletRequest request, ServletContext context);
|
protected abstract WidgetTemplateValues process(Environment env, Map params,
|
||||||
|
HttpServletRequest request, ServletContext context);
|
||||||
|
|
||||||
private String processTemplateToString(String widgetName, Environment env, String templateName, Map<String, Object> map) {
|
private String processMacroToString(Environment env, String widgetName, Macro macro, Map<String, Object> map) {
|
||||||
StringWriter out = new StringWriter();
|
StringWriter out = new StringWriter();
|
||||||
Configuration config = env.getConfiguration();
|
|
||||||
try {
|
try {
|
||||||
Template template = config.getTemplate(templateName);
|
String templateString = macro.getChildNodes().get(0).toString();
|
||||||
|
// NB Using this method of creating a template from a string does not allow the widget template to import
|
||||||
|
// other templates (but it can include other templates). We'd need to use a StringTemplateLoader
|
||||||
|
// in the config instead. See StringTemplateLoader API doc.
|
||||||
|
// The problem is that the StringTemplateLoader has to be added to the config's MultiTemplateLoader.
|
||||||
|
// Then to support multi-threading, we can't just add the widget here to the StringTemplateLoader with
|
||||||
|
// the same key, e.g., "widgetTemplate", since one putTemplate() call will clobber a previous one.
|
||||||
|
// We need to give each widget macro template a unique key in the StringTemplateLoader, and check
|
||||||
|
// if it's already there or else add it. Leave this for later.
|
||||||
|
Template template = new Template("widget", new StringReader(templateString), env.getConfiguration());
|
||||||
template.process(map, out);
|
template.process(map, out);
|
||||||
} catch (Throwable th) {
|
} catch (Throwable th) {
|
||||||
log.error("Could not process widget " + widgetName, th);
|
log.error("Could not process widget " + widgetName, th);
|
||||||
}
|
}
|
||||||
return out.toString();
|
return out.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String processTemplateToString(String widgetName, Environment env, WidgetTemplateValues values) {
|
private String processMacroToString(Environment env, String widgetName, String macroName, Map<String, Object> map) {
|
||||||
return processTemplateToString(widgetName, env, values.getTemplateName(), values.getMap());
|
Macro macro = getMacroFromTemplate(macroName, widgetName, env);
|
||||||
|
return processMacroToString(env, widgetName, macro, map);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String processMacroToString(Environment env, String widgetName, WidgetTemplateValues values) {
|
||||||
|
return processMacroToString(env, widgetName, values.getMacroName(), values.getMap());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Macro getMacroFromTemplate(String macroName, String widgetName, Environment env) {
|
||||||
|
String templateName = getTemplateName(widgetName);
|
||||||
|
Template template = null;
|
||||||
|
Macro macro = null;
|
||||||
|
try {
|
||||||
|
template = env.getConfiguration().getTemplate(templateName);
|
||||||
|
macro = (Macro)template.getMacros().get(macroName);
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("Cannot get template " + templateName);
|
||||||
|
}
|
||||||
|
return macro;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected static class WidgetTemplateValues {
|
protected static class WidgetTemplateValues {
|
||||||
private final String templateName;
|
private final String macroName;
|
||||||
private final Map<String, Object> map;
|
private final Map<String, Object> map;
|
||||||
|
|
||||||
public WidgetTemplateValues(String templateName, Map<String, Object> map) {
|
public WidgetTemplateValues(String templateName, Map<String, Object> map) {
|
||||||
this.templateName = templateName;
|
this.macroName = templateName;
|
||||||
this.map = map;
|
this.map = map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,8 +149,8 @@ public abstract class Widget {
|
||||||
return Collections.unmodifiableMap(this.map);
|
return Collections.unmodifiableMap(this.map);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getTemplateName() {
|
public String getMacroName() {
|
||||||
return this.templateName;
|
return this.macroName;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,11 +11,11 @@
|
||||||
<li> elements. An <li> element may span multiple lines.
|
<li> elements. An <li> element may span multiple lines.
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
<@firstLastList>
|
<@firstLastList />
|
||||||
<li>apples</li>
|
<li>apples</li>
|
||||||
<li>bananas</li>
|
<li>bananas</li>
|
||||||
<li>oranges</li>
|
<li>oranges</li>
|
||||||
</@firstLastList>
|
</@firstLastList />
|
||||||
|
|
||||||
RY Consider rewriting in Java. Probably designers won't want to modify this. That would allow us to support
|
RY Consider rewriting in Java. Probably designers won't want to modify this. That would allow us to support
|
||||||
nested <li> elements.
|
nested <li> elements.
|
||||||
|
@ -47,19 +47,19 @@
|
||||||
indicate how to split the text.
|
indicate how to split the text.
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
<@firstLastListNested>
|
<@firstLastListNested />
|
||||||
<li>apples</li>,
|
<li>apples</li>,
|
||||||
<li>bananas</li>,
|
<li>bananas</li>,
|
||||||
<li>oranges</li>
|
<li>oranges</li>
|
||||||
</@firstLastListNested>
|
</@firstLastListNested />
|
||||||
|
|
||||||
<@firstLastListNested delim="??">
|
<@firstLastListNested delim="??" />
|
||||||
<li>apples, oranges</li>??
|
<li>apples, oranges</li>??
|
||||||
<li>bananas, lemons</li>??
|
<li>bananas, lemons</li>??
|
||||||
<li>grapefruit, limes</li>
|
<li>grapefruit, limes</li>
|
||||||
</@firstLastListNested>
|
</@firstLastListNested />
|
||||||
|
|
||||||
<@firstLastListNested delim="??">
|
<@firstLastListNested delim="??" />
|
||||||
<li>Books
|
<li>Books
|
||||||
<ul>
|
<ul>
|
||||||
<li>Persuasion</li>
|
<li>Persuasion</li>
|
||||||
|
@ -72,7 +72,7 @@
|
||||||
<li>Time</li>
|
<li>Time</li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
</@firstLastListNested>
|
</@firstLastListNested />
|
||||||
|
|
||||||
RY Consider rewriting in Java. Probably designers won't want to modify this.
|
RY Consider rewriting in Java. Probably designers won't want to modify this.
|
||||||
-->
|
-->
|
||||||
|
|
|
@ -1,5 +0,0 @@
|
||||||
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
|
|
||||||
|
|
||||||
${stylesheets.add("/css/test.css")}
|
|
||||||
${scripts.add("/js/testscript.js")}
|
|
||||||
${headScripts.add("/js/testheadscript.js")}
|
|
|
@ -1,6 +0,0 @@
|
||||||
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
|
|
||||||
|
|
||||||
<div class="testWidget">
|
|
||||||
<h4>This is the test widget.</h4>
|
|
||||||
<p>I like ${fruit}.</p>
|
|
||||||
</div>
|
|
|
@ -9,8 +9,16 @@
|
||||||
</#macro>
|
</#macro>
|
||||||
|
|
||||||
<#macro markup>
|
<#macro markup>
|
||||||
|
<#import "lib-list.ftl" as l>
|
||||||
<div class="testWidget">
|
<div class="testWidget">
|
||||||
<h4>This is the test widget.</h4>
|
<h4>This is the test widget using macros.</h4>
|
||||||
<p>I like ${fruit}.</p>
|
<p>I like ${fruit}.</p>
|
||||||
</div>
|
</div>
|
||||||
|
</#macro>
|
||||||
|
|
||||||
|
<#macro altMarkup>
|
||||||
|
<div class="testWidget">
|
||||||
|
<h4>This is the alternate version of the test widget.</h4>
|
||||||
|
<p>I hate ${fruit}.</p>
|
||||||
|
</div>
|
||||||
</#macro>
|
</#macro>
|
Loading…
Add table
Add a link
Reference in a new issue