diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/widgets/LoginWidget.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/widgets/LoginWidget.java index c8e0bbbf9..5132ecb3c 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/widgets/LoginWidget.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/widgets/LoginWidget.java @@ -18,10 +18,11 @@ public class LoginWidget extends Widget { private static final Log log = LogFactory.getLog(LoginWidget.class); @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 map = new HashMap(); map.put("fruit", "bananas"); - return new WidgetTemplateValues (getMarkupTemplateName(widgetName), map); + return new WidgetTemplateValues (getMarkupMacroName(), map); } } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/widgets/TestWidget.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/widgets/TestWidget.java index 614b31672..bc7cc918d 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/widgets/TestWidget.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/widgets/TestWidget.java @@ -13,10 +13,11 @@ import freemarker.core.Environment; public class TestWidget extends Widget { @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 map = new HashMap(); map.put("fruit", "bananas"); - return new WidgetTemplateValues (getMarkupTemplateName(widgetName), map); + return new WidgetTemplateValues (getMarkupMacroName(), map); } } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/widgets/Widget.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/widgets/Widget.java index a0f415a38..1f288cd81 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/widgets/Widget.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/widgets/Widget.java @@ -3,6 +3,7 @@ package edu.cornell.mannlib.vitro.webapp.web.widgets; import java.io.IOException; +import java.io.StringReader; import java.io.StringWriter; import java.util.Collections; import java.util.HashMap; @@ -14,9 +15,8 @@ import javax.servlet.http.HttpServletRequest; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import freemarker.cache.TemplateLoader; import freemarker.core.Environment; -import freemarker.template.Configuration; +import freemarker.core.Macro; import freemarker.template.Template; import freemarker.template.TemplateHashModel; import freemarker.template.TemplateModelException; @@ -31,18 +31,12 @@ public abstract class Widget { public String doAssets(Environment env, Map params) { String widgetName = params.get("name").toString(); //getWidgetName(); - String templateName = getAssetsTemplateName(widgetName); - - // 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); - } + Macro assetsMacro = getMacroFromTemplate(getAssetsMacroName(), widgetName, env); + // Allow there to be no assets macro in the template + if (assetsMacro == null) { + return ""; + } TemplateHashModel dataModel = env.getDataModel(); Map map = new HashMap(); @@ -54,30 +48,36 @@ public abstract class Widget { 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) { HttpServletRequest request = (HttpServletRequest) env.getCustomAttribute("request"); ServletContext context = (ServletContext) env.getCustomAttribute("context"); + + WidgetTemplateValues values = process(env, params, request, context); String widgetName = params.get("name").toString(); // getWidgetName(); - WidgetTemplateValues values = process(env, params, widgetName, request, context); - return processTemplateToString(widgetName, env, values); + return processMacroToString(env, widgetName, values); } - // Default assets template name. Can be overridden by subclasses. - protected String getAssetsTemplateName(String widgetName) { - return "widget-" + widgetName + "-assets.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 template name. Can be overridden by subclasses. + protected String getTemplateName(String widgetName) { + return "widget-" + widgetName + ".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() { // String name = this.getClass().getName(); // name= name.replaceAll(".*\\.", ""); @@ -86,31 +86,57 @@ public abstract class Widget { // 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 map) { + private String processMacroToString(Environment env, String widgetName, Macro macro, Map map) { StringWriter out = new StringWriter(); - Configuration config = env.getConfiguration(); 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); } catch (Throwable th) { log.error("Could not process widget " + widgetName, th); } - return out.toString(); + return out.toString(); } - private String processTemplateToString(String widgetName, Environment env, WidgetTemplateValues values) { - return processTemplateToString(widgetName, env, values.getTemplateName(), values.getMap()); + private String processMacroToString(Environment env, String widgetName, String macroName, Map map) { + 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 { - private final String templateName; + private final String macroName; private final Map map; public WidgetTemplateValues(String templateName, Map map) { - this.templateName = templateName; + this.macroName = templateName; this.map = map; } @@ -123,8 +149,8 @@ public abstract class Widget { return Collections.unmodifiableMap(this.map); } - public String getTemplateName() { - return this.templateName; + public String getMacroName() { + return this.macroName; } } diff --git a/webapp/web/templates/freemarker/lib/lib-list.ftl b/webapp/web/templates/freemarker/lib/lib-list.ftl index e529ad4cf..e75ca5701 100644 --- a/webapp/web/templates/freemarker/lib/lib-list.ftl +++ b/webapp/web/templates/freemarker/lib/lib-list.ftl @@ -11,11 +11,11 @@
  • elements. An
  • element may span multiple lines. Usage: - <@firstLastList> + <@firstLastList />
  • apples
  • bananas
  • oranges
  • - + RY Consider rewriting in Java. Probably designers won't want to modify this. That would allow us to support nested
  • elements. @@ -47,19 +47,19 @@ indicate how to split the text. Usage: - <@firstLastListNested> + <@firstLastListNested />
  • apples
  • ,
  • bananas
  • ,
  • oranges
  • - + - <@firstLastListNested delim="??"> + <@firstLastListNested delim="??" />
  • apples, oranges
  • ??
  • bananas, lemons
  • ??
  • grapefruit, limes
  • - + - <@firstLastListNested delim="??"> + <@firstLastListNested delim="??" />
  • Books
    • Persuasion
    • @@ -72,7 +72,7 @@
    • Time
  • - + RY Consider rewriting in Java. Probably designers won't want to modify this. --> diff --git a/webapp/web/templates/freemarker/widgets/test/widget-test-assets.ftl b/webapp/web/templates/freemarker/widgets/test/widget-test-assets.ftl deleted file mode 100644 index bfb83d06f..000000000 --- a/webapp/web/templates/freemarker/widgets/test/widget-test-assets.ftl +++ /dev/null @@ -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")} \ No newline at end of file diff --git a/webapp/web/templates/freemarker/widgets/test/widget-test-markup.ftl b/webapp/web/templates/freemarker/widgets/test/widget-test-markup.ftl deleted file mode 100644 index 3e56da1b5..000000000 --- a/webapp/web/templates/freemarker/widgets/test/widget-test-markup.ftl +++ /dev/null @@ -1,6 +0,0 @@ -<#-- $This file is distributed under the terms of the license in /doc/license.txt$ --> - -
    -

    This is the test widget.

    -

    I like ${fruit}.

    -
    \ No newline at end of file diff --git a/webapp/web/templates/freemarker/widgets/widget-test.ftl b/webapp/web/templates/freemarker/widgets/widget-test.ftl index a9300ecbc..3571a2909 100644 --- a/webapp/web/templates/freemarker/widgets/widget-test.ftl +++ b/webapp/web/templates/freemarker/widgets/widget-test.ftl @@ -9,8 +9,16 @@ <#macro markup> +<#import "lib-list.ftl" as l>
    -

    This is the test widget.

    +

    This is the test widget using macros.

    I like ${fruit}.

    + + +<#macro altMarkup> +
    +

    This is the alternate version of the test widget.

    +

    I hate ${fruit}.

    +
    \ No newline at end of file