Modify default FreeMarker bean wrapper so template data is read-only. Use different bean wrapper for script and stylesheet objects. Added methods to IndividualView class.

This commit is contained in:
rjy7 2010-06-08 22:24:12 +00:00
parent b27617696f
commit 4c3259163b
5 changed files with 66 additions and 18 deletions

View file

@ -6,8 +6,10 @@ import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.io.StringWriter; import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import javax.servlet.ServletContext; import javax.servlet.ServletContext;
@ -37,6 +39,8 @@ import freemarker.cache.FileTemplateLoader;
import freemarker.cache.MultiTemplateLoader; import freemarker.cache.MultiTemplateLoader;
import freemarker.cache.TemplateLoader; import freemarker.cache.TemplateLoader;
import freemarker.template.Configuration; import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapper;
import freemarker.template.ObjectWrapper;
import freemarker.template.Template; import freemarker.template.Template;
import freemarker.template.TemplateException; import freemarker.template.TemplateException;
import freemarker.template.TemplateModelException; import freemarker.template.TemplateModelException;
@ -127,10 +131,24 @@ public class FreeMarkerHttpServlet extends VitroHttpServlet {
setLoginInfo(); setLoginInfo();
setCopyrightInfo(); setCopyrightInfo();
setThemeInfo(themeDir); setThemeInfo(themeDir);
setScriptAndStylesheetObjects(themeDir);
}
private void setScriptAndStylesheetObjects(String themeDir) {
// Temporarily switch to an object wrapper that exposes write methods.
// The templates can add files to the script and stylesheet lists
// by calling the add() method.
ObjectWrapper defaultWrapper = config.getObjectWrapper();
config.setObjectWrapper(new DefaultObjectWrapper());
// Here themeDir SHOULD NOT have the context path already added to it. // Here themeDir SHOULD NOT have the context path already added to it.
setSharedVariable("stylesheets", new StylesheetList(themeDir)); setSharedVariable("stylesheets", new StylesheetList(themeDir));
setSharedVariable("scripts", new ScriptList()); setSharedVariable("scripts", new ScriptList());
config.setObjectWrapper(defaultWrapper);
} }
// Define template locations. Template loader will look first in the theme-specific // Define template locations. Template loader will look first in the theme-specific

View file

@ -11,6 +11,7 @@ import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.ConfigurationProperties; import edu.cornell.mannlib.vitro.webapp.ConfigurationProperties;
import edu.cornell.mannlib.vitro.webapp.view.ViewObject; import edu.cornell.mannlib.vitro.webapp.view.ViewObject;
import freemarker.ext.beans.BeansWrapper;
import freemarker.template.Configuration; import freemarker.template.Configuration;
import freemarker.template.DefaultObjectWrapper; import freemarker.template.DefaultObjectWrapper;
import freemarker.template.TemplateException; import freemarker.template.TemplateException;
@ -39,10 +40,13 @@ public class FreeMarkerSetup implements ServletContextListener {
cfg.setTemplateUpdateDelay(0); // no template caching in development cfg.setTemplateUpdateDelay(0); // no template caching in development
} }
// Specify how templates will see the data-model. This is an advanced topic... // Specify how templates will see the data-model.
// but just use this: // The default wrapper exposes set methods unless exposure level is set.
cfg.setObjectWrapper(new DefaultObjectWrapper()); // By default we want to block exposure of set methods.
// cfg.setObjectWrapper(new DefaultObjectWrapper());
BeansWrapper wrapper = new DefaultObjectWrapper();
wrapper.setExposureLevel(BeansWrapper.EXPOSE_PROPERTIES_ONLY);
cfg.setObjectWrapper(wrapper);
// Set some formatting defaults. These can be overridden at the template // Set some formatting defaults. These can be overridden at the template
// or environment (template-processing) level, or for an individual // or environment (template-processing) level, or for an individual

View file

@ -26,25 +26,17 @@ public class IndividualView extends ViewObject {
this.individual = individual; this.individual = individual;
} }
public String getName() { /* These methods perform some manipulation of the data returned by the Individual methods */
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;
} }
public String getUri() {
return individual.getURI();
}
// Return link to individual's profile page. // Return link to individual's profile page.
// There may be other urls associated with the individual. E.g., we might need // There may be other urls associated with the individual. E.g., we might need
// getEditUrl(), getDeleteUrl() to return the links computed by PropertyEditLinks. // getEditUrl(), getDeleteUrl() to return the links computed by PropertyEditLinks.
// RY **** Need to account for everything in URLRewritingHttpServlet // RY **** Need to account for everything in URLRewritingHttpServlet
// Currently this is incorrect for individuals that are not in the default namespace (e.g., geographic individuals).
public String getProfileUrl() { public String getProfileUrl() {
return getUrl(PATH + "/" + individual.getLocalName()); return getUrl(PATH + "/" + individual.getLocalName());
} }
@ -78,6 +70,9 @@ public class IndividualView extends ViewObject {
return primaryLink; return primaryLink;
} }
// RY Here we really want to return List<LinkView> objects. Instead of writing the LinkView class by hand,
// it would be better to use an alternate FreeMarker BeanWrapper that creates a read-only template data object.
// That would also be used to return the lists of object properties and data properties of the individual.
public List<Link> getLinks() { public List<Link> getLinks() {
List<Link> additionalLinks = individual.getLinksList(); List<Link> additionalLinks = individual.getLinksList();
List<Link> links = new ArrayList<Link>(additionalLinks.size()+1); List<Link> links = new ArrayList<Link>(additionalLinks.size()+1);
@ -89,4 +84,38 @@ public class IndividualView extends ViewObject {
return links; return links;
} }
/* These methods simply forward to the Individual methods. It would be desirable to implement a scheme
for proxying or delegation so that the methods don't need to be simply listed here.
A Ruby-style method missing method would be ideal. */
public String getName() {
return individual.getName();
}
public String getUri() {
return individual.getURI();
}
public String getDescription() {
return individual.getDescription();
}
public String getBlurb() {
return individual.getBlurb();
}
public String getCitation() {
return individual.getBlurb();
}
public List<String> getKeywords() {
return individual.getKeywords();
}
public String getImageFile() {
return individual.getImageFile();
}
public String getImageThumb() {
return individual.getImageThumb();
}
} }

View file

@ -55,6 +55,4 @@
</div> </div>
<#-- RY This is temporary.
<script src="${contextPath}/js/commentForm.js"></script>-->
${scripts.add("/js/commentForm.js")} ${scripts.add("/js/commentForm.js")}

View file

@ -9,7 +9,6 @@
<@l.firstLastList> <@l.firstLastList>
<li>${individual.tagline}</li>, <li>${individual.tagline}</li>,
<#list individual.links as link> <#list individual.links as link>
${link.setAnchor("Changing Anchor Text")}
<li><a class="externalLink" href="${link.url}">${link.anchor}</a></li>, <li><a class="externalLink" href="${link.url}">${link.anchor}</a></li>,
</#list> </#list>
</@l.firstLastList> </@l.firstLastList>