Title: [waffle-scm] [683] trunk: WAFFLE-81: Added support for sitemesh decoration of processed views.

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:

http://xircles.codehaus.org/manage_email

Reply via email to