You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by th...@apache.org on 2014/01/09 19:47:45 UTC

git commit: TAP5-938: Expose ability to render a portion of a page (a Block, Component, etc.) without using internal services

Updated Branches:
  refs/heads/master 10425b8ee -> 8b7be0060


TAP5-938: Expose ability to render a portion of a page (a Block,
Component, etc.) without using internal services

Project: http://git-wip-us.apache.org/repos/asf/tapestry-5/repo
Commit: http://git-wip-us.apache.org/repos/asf/tapestry-5/commit/8b7be006
Tree: http://git-wip-us.apache.org/repos/asf/tapestry-5/tree/8b7be006
Diff: http://git-wip-us.apache.org/repos/asf/tapestry-5/diff/8b7be006

Branch: refs/heads/master
Commit: 8b7be0060db3b4995896211eae26242559ece227
Parents: 10425b8
Author: Thiago H. de Paula Figueiredo <th...@apache.org>
Authored: Thu Jan 9 16:47:22 2014 -0200
Committer: Thiago H. de Paula Figueiredo <th...@apache.org>
Committed: Thu Jan 9 16:47:22 2014 -0200

----------------------------------------------------------------------
 .../services/PartialTemplateRendererImpl.java   | 71 +++++++++++++++
 .../tapestry5/modules/TapestryModule.java       |  1 +
 .../services/PartialTemplateRenderer.java       | 66 ++++++++++++++
 .../test/app1/PartialTemplateRendererDemo.tml   | 25 ++++++
 .../app1/PartialTemplateRendererTests.groovy    | 63 +++++++++++++
 .../tapestry5/integration/app1/pages/Index.java |  4 +-
 .../app1/pages/PartialTemplateRendererDemo.java | 94 ++++++++++++++++++++
 7 files changed, 323 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/8b7be006/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PartialTemplateRendererImpl.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PartialTemplateRendererImpl.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PartialTemplateRendererImpl.java
new file mode 100644
index 0000000..4a8f62f
--- /dev/null
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/PartialTemplateRendererImpl.java
@@ -0,0 +1,71 @@
+// Copyright 2014, The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package org.apache.tapestry5.internal.services;
+
+import org.apache.tapestry5.MarkupWriter;
+import org.apache.tapestry5.dom.Document;
+import org.apache.tapestry5.ioc.services.TypeCoercer;
+import org.apache.tapestry5.runtime.RenderCommand;
+import org.apache.tapestry5.services.PartialTemplateRenderer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class PartialTemplateRendererImpl implements PartialTemplateRenderer
+{
+    
+    final private static Logger LOGGER = LoggerFactory.getLogger(PartialTemplateRendererImpl.class);
+    
+    final private TypeCoercer typeCoercer;
+
+    public PartialTemplateRendererImpl(TypeCoercer typeCoercer)
+    {
+        super();
+        this.typeCoercer = typeCoercer;
+    }
+
+    public Document renderAsDocument(Object object)
+    {
+        RenderCommand renderCommand = toRenderCommand(object);
+        MarkupWriter markupWriter = new MarkupWriterImpl(); 
+        RenderQueueImpl renderQueue = new RenderQueueImpl(LOGGER); 
+        renderQueue.push(renderCommand); 
+        renderQueue.run(markupWriter);
+        return markupWriter.getDocument();
+    }
+
+    public String render(Object object)
+    {
+        return renderAsDocument(object).toString();
+    }
+
+    private RenderCommand toRenderCommand(Object object)
+    {
+        RenderCommand renderCommand = null;
+        if (object instanceof RenderCommand)
+        {
+            renderCommand = (RenderCommand) object;
+        }
+        else {
+            try {
+                renderCommand = typeCoercer.coerce(object, RenderCommand.class); 
+            }
+            catch (RuntimeException e) {
+                throw new IllegalArgumentException(
+                        String.format("Couldn't find a coercion from %s to RenderCommand", object.getClass().getName()), e);
+            }
+        }
+        return renderCommand;
+    }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/8b7be006/tapestry-core/src/main/java/org/apache/tapestry5/modules/TapestryModule.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/modules/TapestryModule.java b/tapestry-core/src/main/java/org/apache/tapestry5/modules/TapestryModule.java
index 4393236..0939811 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/modules/TapestryModule.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/modules/TapestryModule.java
@@ -371,6 +371,7 @@ public final class TapestryModule
         binder.bind(ValueEncoderSource.class, ValueEncoderSourceImpl.class);
         binder.bind(PathConstructor.class, PathConstructorImpl.class);
         binder.bind(DateUtilities.class, DateUtilitiesImpl.class);
+        binder.bind(PartialTemplateRenderer.class, PartialTemplateRendererImpl.class);
     }
 
     // ========================================================================

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/8b7be006/tapestry-core/src/main/java/org/apache/tapestry5/services/PartialTemplateRenderer.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/services/PartialTemplateRenderer.java b/tapestry-core/src/main/java/org/apache/tapestry5/services/PartialTemplateRenderer.java
new file mode 100644
index 0000000..e4a595a
--- /dev/null
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/services/PartialTemplateRenderer.java
@@ -0,0 +1,66 @@
+// Copyright 2014, The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package org.apache.tapestry5.services;
+
+import org.apache.tapestry5.Block;
+import org.apache.tapestry5.alerts.Alert;
+import org.apache.tapestry5.dom.Document;
+import org.apache.tapestry5.dom.Element;
+import org.apache.tapestry5.ioc.services.TypeCoercer;
+import org.apache.tapestry5.runtime.RenderCommand;
+
+/**
+ * <p>
+ * Service that provides methods that render {@link Block}s (<code>&ltt:block&gt>)</code>,
+ * component instances and {@link RenderCommand}s to a {@link String} or 
+ * {@link Document org.apache.tapestry5.dom.Document} in a programatic way.
+ * </p>
+ * <p>
+ * This service was created for situations in which a page or component needs to generate some markup
+ * that wouldn't be rendered normally, but for external use, such as e-mails, returning
+ * HTML for AJAX requests or passing HTML instead of plain string for an {@link Alert}.
+ * </p>
+ * <p>
+ * The name of this interface comes from <a href="https://issues.apache.org/jira/browse/TAP5-938">TAP5-938</a>:
+ * <em>Expose ability to render a portion of a page (a Block, Component, etc.) without using internal services</em>.
+ * </p>
+ * @since 5.4
+ */
+public interface PartialTemplateRenderer
+{
+
+    /**
+     * <p>
+     * Renders an object, probably a {@link Block} or component instance, to a string. 
+     * This method supposes any kind of initialization needed
+     * was already done. CSS and JavaScript inclusions or importings are ignored.
+     * The object must implement {@link RenderCommand} or being able to be coerced to it
+     * by {@link TypeCoercer}.
+     * <p>
+     * @param object an object, probably a {@link Block} or component instance or {@link RenderCommand}.
+     * @throws IllegalArgumentException if the object isn't a {@link RenderCommand} and cannot be coerced to it by {@link TypeCoercer}.
+     */
+    String render(Object object);
+    
+    /**
+     * Renders an object to a {@link Document} following the same rules as {@link #render(Object)}
+     * This method supposes any kind of initialization needed
+     * was already done. CSS and JavaScript inclusions or importings are ignored.
+     * 
+     * @param renderCommand a {@link RenderCommand}.
+     * @return a {@link Document}.
+     */
+    Document renderAsDocument(Object object);
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/8b7be006/tapestry-core/src/test/app1/PartialTemplateRendererDemo.tml
----------------------------------------------------------------------
diff --git a/tapestry-core/src/test/app1/PartialTemplateRendererDemo.tml b/tapestry-core/src/test/app1/PartialTemplateRendererDemo.tml
new file mode 100644
index 0000000..6f41863
--- /dev/null
+++ b/tapestry-core/src/test/app1/PartialTemplateRendererDemo.tml
@@ -0,0 +1,25 @@
+<t:border xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd"
+          xmlns:p="tapestry:parameter">
+
+	<t:block id="someBlock">
+		<!-- One component that generates a good amount of markup -->
+		<t:beandisplay t:id="insideBlock" t:object="object"/>
+	</t:block>
+	
+	<div id="original">
+		<t:delegate to="block:someblock"/>
+	</div>
+	
+	<div id="serviceRenderedBlock">
+		<t:outputRaw value="serviceRenderedBlock"/>
+	</div>
+	
+	<div id="originalBeanDisplay">
+		<t:beandisplay t:id="beanDisplay" t:object="object"/>
+	</div>
+
+	<div id="serviceRenderedComponent">
+		<t:outputRaw value="serviceRenderedComponent"/>
+	</div>
+
+</t:border>

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/8b7be006/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/PartialTemplateRendererTests.groovy
----------------------------------------------------------------------
diff --git a/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/PartialTemplateRendererTests.groovy b/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/PartialTemplateRendererTests.groovy
new file mode 100644
index 0000000..5943a69
--- /dev/null
+++ b/tapestry-core/src/test/groovy/org/apache/tapestry5/integration/app1/PartialTemplateRendererTests.groovy
@@ -0,0 +1,63 @@
+// Copyright 2014 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry5.integration.app1
+
+import org.apache.tapestry5.services.PartialTemplateRenderer;
+import org.testng.annotations.Test
+import org.junit.Assert;
+
+/**
+ * Tests the {@link PartialTemplateRenderer} service.
+ *
+ * @since 5.4
+ */
+class PartialTemplateRendererTests extends App1TestCase {
+
+    @Test
+    void render_block() {
+        
+        open "/partialtemplaterendererdemo"
+
+        assertEquals(getAttribute("css=#original dl@class"), getAttribute("css=#serviceRenderedBlock dl@class"))
+        
+        // checking whether service-rendered block is the same as the original
+        for (int i = 1; i <= getXpathCount("//div[@id='original']/dl/*"); i++) {
+            
+            assertEquals(
+                getAttribute("//div[@id='original']/dl/*[" + i + "]@class"),
+                getAttribute("//div[@id='serviceRenderedBlock']/dl/*[" + i + "]/@class")) 
+
+            assertEquals(
+                getText("//div[@id='original']/dl/*[" + i + "]"),
+                getText("//div[@id='serviceRenderedBlock']/dl/*[" + i + "]"))
+
+        } 
+
+        // checking whether service-rendered component is the same as the original
+        for (int i = 1; i <= getXpathCount("//div[@id='original']/dl/*"); i++) {
+            
+            assertEquals(
+                getAttribute("//div[@id='originalBeanDisplay']/dl/*[" + i + "]@class"),
+                getAttribute("//div[@id='serviceRenderedComponent']/dl/*[" + i + "]/@class"))
+
+            assertEquals(
+                getText("//div[@id='originalBeanDisplay']/dl/*[" + i + "]"),
+                getText("//div[@id='serviceRenderedComponent']/dl/*[" + i + "]"))
+
+        }
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/8b7be006/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java
index a3f2337..3d276ca 100644
--- a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java
+++ b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/Index.java
@@ -547,7 +547,9 @@ public class Index
 					new Item("UnknownActivationContextDemo", "Unknown Activation Context Demo", "Page refuse to serve if called with an unknown activation context (TAP5-2070)",
 							"Unwanted", "context"),
                     
-                    new Item("ModuleConfigurationCallbackDemo", "ModuleConfigurationCallback Demo", "Shows an example of changing the Require.js configuration using JavaScriptSupport.addModuleConfigurationDemo()")
+                    new Item("ModuleConfigurationCallbackDemo", "ModuleConfigurationCallback Demo", "Shows an example of changing the Require.js configuration using JavaScriptSupport.addModuleConfigurationDemo()"),
+                    
+                    new Item("PartialTemplateRendererDemo", "PartialTemplateRenderer Demo", "Shows some examples of rendering blocks and components to a String using PartialTemplateRenderer")
 
             );
 

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/8b7be006/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/PartialTemplateRendererDemo.java
----------------------------------------------------------------------
diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/PartialTemplateRendererDemo.java b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/PartialTemplateRendererDemo.java
new file mode 100644
index 0000000..ecd2fb3
--- /dev/null
+++ b/tapestry-core/src/test/java/org/apache/tapestry5/integration/app1/pages/PartialTemplateRendererDemo.java
@@ -0,0 +1,94 @@
+// Copyright 2009-2013 The Apache Software Foundation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package org.apache.tapestry5.integration.app1.pages;
+
+import java.util.Date;
+
+import org.apache.tapestry5.Block;
+import org.apache.tapestry5.annotations.InjectComponent;
+import org.apache.tapestry5.annotations.Property;
+import org.apache.tapestry5.corelib.components.BeanDisplay;
+import org.apache.tapestry5.ioc.annotations.Inject;
+import org.apache.tapestry5.services.PartialTemplateRenderer;
+
+public class PartialTemplateRendererDemo
+{
+    
+    @Inject
+    @Property
+    private Block someBlock;
+    
+    @Inject
+    private PartialTemplateRenderer partialTemplateRenderer;
+    
+    @InjectComponent
+    private BeanDisplay beanDisplay;
+    
+    @Property
+    private Pojo object;
+    
+    void setupRender() {
+        object = new Pojo();
+        object.setDate(new Date(21342345234444L));
+        object.setString(String.valueOf(System.currentTimeMillis()));
+        object.setInteger((int) (System.currentTimeMillis() % 234123));
+    }
+    
+    public String getServiceRenderedBlock() {
+        return partialTemplateRenderer.render(someBlock);
+    }
+
+    public String getServiceRenderedComponent() {
+        return partialTemplateRenderer.render(beanDisplay);
+    }
+
+    public static class Pojo
+    {
+        private int integer;
+        private String string;
+        private Date date;
+
+        public int getInteger()
+        {
+            return integer;
+        }
+
+        public void setInteger(int i)
+        {
+            this.integer = i;
+        }
+
+        public String getString()
+        {
+            return string;
+        }
+
+        public void setString(String s)
+        {
+            this.string = s;
+        }
+
+        public Date getDate()
+        {
+            return date;
+        }
+
+        public void setDate(Date date)
+        {
+            this.date = date;
+        }
+
+    }
+}