- Revision
- 683
- Author
- mauro
- Date
- 2008-05-20 08:07:04 -0500 (Tue, 20 May 2008)
Log Message
WAFFLE-81: Added support for sitemesh decoration of processed views.
Modified Paths
- trunk/.classpath
- trunk/waffle-testing/pom.xml
- trunk/waffle-testing/src/main/java/org/codehaus/waffle/testing/view/ViewHarness.java
- trunk/waffle-testing/src/main/java/org/codehaus/waffle/testing/view/ViewProcessor.java
- trunk/waffle-testing/src/main/java/org/codehaus/waffle/testing/view/freemarker/FreemarkerProcessor.java
- trunk/waffle-testing/src/test/java/org/codehaus/waffle/testing/view/ViewHarnessTest.java
Added Paths
- trunk/waffle-testing/src/main/java/org/codehaus/waffle/testing/view/sitemesh/
- trunk/waffle-testing/src/main/java/org/codehaus/waffle/testing/view/sitemesh/SitemeshDecorator.java
- trunk/waffle-testing/src/test/webapp/WEB-INF/
- trunk/waffle-testing/src/test/webapp/WEB-INF/decorators/
- trunk/waffle-testing/src/test/webapp/WEB-INF/decorators/layout.ftl
- trunk/waffle-testing/src/test/webapp/WEB-INF/testing-decorators.xml
- trunk/waffle-testing/src/test/webapp/freemarker/footer.ftl
- trunk/waffle-testing/src/test/webapp/freemarker/header.ftl
- trunk/waffle-testing/src/test/webapp/freemarker/resources.ftl
- trunk/waffle-testing/src/test/webapp/style/
- trunk/waffle-testing/src/test/webapp/style/style.css
Diff
Modified: trunk/.classpath (682 => 683)
--- trunk/.classpath 2008-05-19 16:39:54 UTC (rev 682) +++ trunk/.classpath 2008-05-20 13:07:04 UTC (rev 683) @@ -28,20 +28,7 @@ <attribute name="maven.type" value="test"/> </attributes> </classpathentry> - <classpathentry kind="src" output="target-eclipse/classes" path="examples/freemarker-example/src/main/java"/> - <classpathentry kind="src" output="target-eclipse/classes" path="examples/freemarker-example/src/main/webapp"/> - <classpathentry kind="src" output="target-eclipse/test-classes" path="examples/freemarker-example/src/test/java"> - <attributes> - <attribute name="maven.type" value="test"/> - </attributes> - </classpathentry> - <classpathentry kind="src" output="target-eclipse/classes" path="examples/simple-example/src/main/java"/> - <classpathentry kind="src" output="target-eclipse/classes" path="examples/simple-example/src/main/webapp"/> - <classpathentry kind="src" output="target-eclipse/test-classes" path="examples/simple-example/src/test/java"> - <attributes> - <attribute name="maven.type" value="test"/> - </attributes> - </classpathentry> + <classpathentry excluding="**" kind="src" output="waffle-testing/src/test/webapp" path="waffle-testing/src/test/webapp"/> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> <classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER/modules/profiles[examples,integration]"/> <classpathentry kind="output" path="target-eclipse/classes"/>
Modified: trunk/waffle-testing/pom.xml (682 => 683)
--- trunk/waffle-testing/pom.xml 2008-05-19 16:39:54 UTC (rev 682) +++ trunk/waffle-testing/pom.xml 2008-05-20 13:07:04 UTC (rev 683) @@ -1,4 +1,5 @@ -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.codehaus.waffle</groupId> @@ -22,10 +23,22 @@ </dependency> <dependency> <groupId>org.freemarker</groupId> - <artifactId>freemarker</artifactId> + <artifactId>freemarker</artifactId> <version>2.3.12</version> <scope>compile</scope> </dependency> + <dependency> + <groupId>opensymphony</groupId> + <artifactId>sitemesh</artifactId> + <version>2.3</version> + <scope>compile</scope> + </dependency> + <dependency> + <groupId>commons-io</groupId> + <artifactId>commons-io</artifactId> + <version>1.4</version> + <scope>compile</scope> + </dependency> </dependencies> <build> <testResources> @@ -39,5 +52,5 @@ <directory>${basedir}/src/test/webapp</directory> </testResource> </testResources> - </build> + </build> </project> \ No newline at end of file
Modified: trunk/waffle-testing/src/main/java/org/codehaus/waffle/testing/view/ViewHarness.java (682 => 683)
--- trunk/waffle-testing/src/main/java/org/codehaus/waffle/testing/view/ViewHarness.java 2008-05-19 16:39:54 UTC (rev 682) +++ trunk/waffle-testing/src/main/java/org/codehaus/waffle/testing/view/ViewHarness.java 2008-05-20 13:07:04 UTC (rev 683) @@ -6,6 +6,7 @@ import java.io.OutputStream; import org.codehaus.waffle.testing.view.freemarker.FreemarkerProcessor; +import org.codehaus.waffle.testing.view.sitemesh.SitemeshDecorator; /** * Facade that enable processing of views by different template engines. The choice of engine is made based on the @@ -15,24 +16,34 @@ */ public class ViewHarness { - enum Template { + enum Type { FREEMARKER }; public String process(String resource, Object controller) { - Template template = templateFor(resource); - switch (template) { + return process(typeFor(resource), resource, controller); + } + + public String process(Type type, String resource, Object controller) { + return processorFor(type).process(resource, controller); + } + + public ViewProcessor processorFor(Type type) { + switch (type) { case FREEMARKER: - FreemarkerProcessor processor = new FreemarkerProcessor(); - return processor.process(resource, controller); + return new FreemarkerProcessor(); default: - throw new UnknownTemplateTypeException(resource); + throw new UnknownTemplateTypeException(type.name()); } } - private Template templateFor(String resource) { + public ViewProcessor processorFor(String resource) { + return processorFor(typeFor(resource)); + } + + public Type typeFor(String resource) { if (resource.endsWith(".ftl")) { - return Template.FREEMARKER; + return Type.FREEMARKER; } throw new UnknownTemplateTypeException(resource); } @@ -63,29 +74,41 @@ } /** - * Exports a view to a file + * Decorates a view with Sitemesh * * @param resource the template resource path * @param controller the controller instance + * @param decoratorsResource the Sitemesh decorators resource + * @param decoratorName the decorator name + * @return The decorated resource + */ + public static String decorateView(String resource, Object controller, String decoratorsResource, + String decoratorName) { + SitemeshDecorator decorator = new SitemeshDecorator(new ViewHarness().processorFor(resource)); + return decorator.decorate(resource, controller, decoratorsResource, decoratorName); + } + + /** + * Exports a view to a file + * + * @param processed the String encoding the processed view * @param output the File to export view to * @throws IOException */ - public static void exportView(String resource, Object controller, File output) throws IOException { + public static void exportView(String processed, File output) throws IOException { File parent = new File(output.getParent()); parent.mkdirs(); - exportView(resource, controller, new FileOutputStream(output)); + exportView(processed, new FileOutputStream(output)); } /** * Exports a view to an output stream * - * @param resource the template resource path - * @param controller the controller instance + * @param processed the String encoding the processed view * @param output the OutputStream to export view to * @throws IOException */ - public static void exportView(String resource, Object controller, OutputStream output) throws IOException { - String processed = new ViewHarness().process(resource, controller); + public static void exportView(String processed, OutputStream output) throws IOException { output.write(processed.getBytes()); } }
Modified: trunk/waffle-testing/src/main/java/org/codehaus/waffle/testing/view/ViewProcessor.java (682 => 683)
--- trunk/waffle-testing/src/main/java/org/codehaus/waffle/testing/view/ViewProcessor.java 2008-05-19 16:39:54 UTC (rev 682) +++ trunk/waffle-testing/src/main/java/org/codehaus/waffle/testing/view/ViewProcessor.java 2008-05-20 13:07:04 UTC (rev 683) @@ -1,8 +1,9 @@ package org.codehaus.waffle.testing.view; +import java.util.Map; + /** * ViewProcessor abstracts the view processing implemented by different template engines, eg Freemarker, Velocity etc. - * * The view expects a single controller instance under key "controller". * * @author Mauro Talevi @@ -18,4 +19,27 @@ */ String process(String resource, Object controller); + /** + * Processes template content with given data model + * + * @param resource the template resource + * @param dataModel the Map<String, Object> holding the data model + * @return The processed content + */ + String process(String resource, Map<String, Object> dataModel); + + /** + * Creates an data model for the given controller. The data model contains: + * <ul> + * <li>"base": ""</li> + * <li>"controller": controller instance</li> + * <li>"errors": the default errors context</li> + * <li>"messages": the default messages context</li> + * </ul> + * + * @param controller the controller instance + * @return A Map<String, Object> + */ + Map<String, Object> createDataModel(Object controller); + }
Modified: trunk/waffle-testing/src/main/java/org/codehaus/waffle/testing/view/freemarker/FreemarkerProcessor.java (682 => 683)
--- trunk/waffle-testing/src/main/java/org/codehaus/waffle/testing/view/freemarker/FreemarkerProcessor.java 2008-05-19 16:39:54 UTC (rev 682) +++ trunk/waffle-testing/src/main/java/org/codehaus/waffle/testing/view/freemarker/FreemarkerProcessor.java 2008-05-20 13:07:04 UTC (rev 683) @@ -24,7 +24,7 @@ */ public class FreemarkerProcessor implements ViewProcessor { - private Configuration configuration; + public Configuration configuration; public FreemarkerProcessor() { this(defaultConfigurationProperties());
Added: trunk/waffle-testing/src/main/java/org/codehaus/waffle/testing/view/sitemesh/SitemeshDecorator.java (0 => 683)
--- trunk/waffle-testing/src/main/java/org/codehaus/waffle/testing/view/sitemesh/SitemeshDecorator.java (rev 0) +++ trunk/waffle-testing/src/main/java/org/codehaus/waffle/testing/view/sitemesh/SitemeshDecorator.java 2008-05-20 13:07:04 UTC (rev 683) @@ -0,0 +1,58 @@ +package org.codehaus.waffle.testing.view.sitemesh; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.Map; + +import org.apache.commons.io.IOUtils; +import org.codehaus.waffle.testing.view.ViewProcessor; + +import com.opensymphony.module.sitemesh.Decorator; +import com.opensymphony.module.sitemesh.Page; +import com.opensymphony.module.sitemesh.PageParser; +import com.opensymphony.module.sitemesh.mapper.ConfigLoader; +import com.opensymphony.module.sitemesh.multipass.DivExtractingPageParser; + +/** + * Sitemesh template decorator + * + * @author Mauro Talevi + */ +public class SitemeshDecorator { + + private final ViewProcessor processor; + + public SitemeshDecorator(ViewProcessor processor) { + this.processor = processor; + } + + public String decorate(String resource, Object controller, String decoratorsResource, String decoratorName) { + try { + ConfigLoader configLoader = new ConfigLoader(createTempFile(decoratorsResource, "decorators-test", ".xml")); + Decorator decorator = configLoader.getDecoratorByName(decoratorName); + PageParser parser = new DivExtractingPageParser(); + Page page = parser.parse(processor.process(resource, controller).toCharArray()); + Map<String, Object> dataModel = processor.createDataModel(controller); + dataModel.put("title", page.getTitle()); + dataModel.put("body", page.getBody()); + return processor.process(decorator.getPage(), dataModel); + } catch (Exception e) { + throw new RuntimeException("Failed to decorate resource", e); + } + } + + private File createTempFile(String resource, String prefix, String suffix) throws IOException { + String content = loadContent(resource); + File file = File.createTempFile(prefix, suffix); + BufferedWriter out = new BufferedWriter(new FileWriter(file)); + out.write(content); + out.close(); + return file; + } + + private String loadContent(String resource) throws IOException { + return IOUtils.toString(Thread.currentThread().getContextClassLoader().getResourceAsStream(resource)); + } +}
Modified: trunk/waffle-testing/src/test/java/org/codehaus/waffle/testing/view/ViewHarnessTest.java (682 => 683)
--- trunk/waffle-testing/src/test/java/org/codehaus/waffle/testing/view/ViewHarnessTest.java 2008-05-19 16:39:54 UTC (rev 682) +++ trunk/waffle-testing/src/test/java/org/codehaus/waffle/testing/view/ViewHarnessTest.java 2008-05-20 13:07:04 UTC (rev 683) @@ -1,5 +1,6 @@ package org.codehaus.waffle.testing.view; +import static org.codehaus.waffle.testing.view.ViewHarness.decorateView; import static org.codehaus.waffle.testing.view.ViewHarness.exportView; import static org.codehaus.waffle.testing.view.ViewHarness.processView; import static org.junit.Assert.assertTrue; @@ -19,17 +20,27 @@ public void canProcessFreemarkerView() { ListController controller = new ListController(); controller.list(); - processView("freemarker/list.ftl", controller, false); + String processed = processView("freemarker/list.ftl", controller, false); + assertTrue(processed.length() > 0); } @Test - public void canExportView() throws IOException { + public void canDecorateWithSitemesh() { ListController controller = new ListController(); controller.list(); - File output = new File("target/export/list.html"); - exportView("freemarker/list.ftl", controller, output); - assertTrue(output.exists()); + String decorated = decorateView("freemarker/list.ftl", controller, "WEB-INF/testing-decorators.xml", "layout"); + assertTrue(decorated.length() > 0); } - + @Test + public void canExportViews() throws IOException { + ListController controller = new ListController(); + controller.list(); + File list = new File("target/export/list.html"); + exportView(processView("freemarker/list.ftl", controller, false), list); + assertTrue(list.exists()); + File decorated = new File("target/export/decorated-list.html"); + exportView(decorateView("freemarker/list.ftl", controller, "WEB-INF/testing-decorators.xml", "layout"), decorated); + assertTrue(decorated.exists()); + } }
Added: trunk/waffle-testing/src/test/webapp/WEB-INF/decorators/layout.ftl (0 => 683)
--- trunk/waffle-testing/src/test/webapp/WEB-INF/decorators/layout.ftl (rev 0) +++ trunk/waffle-testing/src/test/webapp/WEB-INF/decorators/layout.ftl 2008-05-20 13:07:04 UTC (rev 683) @@ -0,0 +1,14 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> + <title>${title}</title> + <#include "/freemarker/resources.ftl" parse="true"> +</head> +<body> +<#include "/freemarker/header.ftl" parse="true"> +<div id="body"> +${body} +</div> +<#include "/freemarker/footer.ftl" parse="true"> +</body> +</html> \ No newline at end of file
Added: trunk/waffle-testing/src/test/webapp/WEB-INF/testing-decorators.xml (0 => 683)
--- trunk/waffle-testing/src/test/webapp/WEB-INF/testing-decorators.xml (rev 0) +++ trunk/waffle-testing/src/test/webapp/WEB-INF/testing-decorators.xml 2008-05-20 13:07:04 UTC (rev 683) @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="ISO-8859-1"?> + +<decorators defaultdir="/WEB-INF/decorators"> + <decorator name="layout" page="layout.ftl"> + <pattern>/*</pattern> + </decorator> +</decorators> \ No newline at end of file
Added: trunk/waffle-testing/src/test/webapp/freemarker/footer.ftl (0 => 683)
--- trunk/waffle-testing/src/test/webapp/freemarker/footer.ftl (rev 0) +++ trunk/waffle-testing/src/test/webapp/freemarker/footer.ftl 2008-05-20 13:07:04 UTC (rev 683) @@ -0,0 +1,5 @@ +<div id="footer"> + <p> + [Footer] + </p> +</div>
Added: trunk/waffle-testing/src/test/webapp/freemarker/header.ftl (0 => 683)
--- trunk/waffle-testing/src/test/webapp/freemarker/header.ftl (rev 0) +++ trunk/waffle-testing/src/test/webapp/freemarker/header.ftl 2008-05-20 13:07:04 UTC (rev 683) @@ -0,0 +1,5 @@ +<div id="header"> + <p> + [Header] + </p> +</div>
Added: trunk/waffle-testing/src/test/webapp/freemarker/resources.ftl (0 => 683)
--- trunk/waffle-testing/src/test/webapp/freemarker/resources.ftl (rev 0) +++ trunk/waffle-testing/src/test/webapp/freemarker/resources.ftl 2008-05-20 13:07:04 UTC (rev 683) @@ -0,0 +1,2 @@ +<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"/> +<link rel="stylesheet" type="text/css" href=""
Added: trunk/waffle-testing/src/test/webapp/style/style.css (0 => 683)
--- trunk/waffle-testing/src/test/webapp/style/style.css (rev 0) +++ trunk/waffle-testing/src/test/webapp/style/style.css 2008-05-20 13:07:04 UTC (rev 683) @@ -0,0 +1,66 @@ +body { + font-family: sans-serif; + font-size: 12px; +} + +fieldset { + margin: 4px 0; + padding: 1px; + border: 1px solid #ccc; + background: white; +} + +fieldset legend { + font-weight: bold; +} + +fieldset p { + vertical-align: bottom; +} + +fieldset label { + width: 120px; + float: left; + text-align: right; + padding: 2px 5px 2px 5px; +} + +fieldset input { + width: 120px; + float: left; + text-align: left; + padding: 2px 5px 2px 5px; +} + +table { + border: solid 1px; + width: 60%; +} + +table th { + font-weight: bold; + background-color: #ccc; +} + +table th,td { + padding-left: 5px; + padding-right: 5px; +} + +.content { + background-color: white; +} + +.errors { + color: red; + border: solid red 2px; + padding: 4px; + margin: 20px 20px 20px 20px; +} + +a,a:active,a:link,a:hover,a:visited { + color: #666; + font-weight: bold; + font-size: 12px; + text-decoration: none +} \ No newline at end of file
To unsubscribe from this list please visit:
