001 // Copyright 2009, 2010, 2011 The Apache Software Foundation
002 //
003 // Licensed under the Apache License, Version 2.0 (the "License");
004 // you may not use this file except in compliance with the License.
005 // You may obtain a copy of the License at
006 //
007 // http://www.apache.org/licenses/LICENSE-2.0
008 //
009 // Unless required by applicable law or agreed to in writing, software
010 // distributed under the License is distributed on an "AS IS" BASIS,
011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012 // See the License for the specific language governing permissions and
013 // limitations under the License.
014
015 package org.apache.tapestry5.internal.services.ajax;
016
017 import org.apache.tapestry5.MarkupWriter;
018 import org.apache.tapestry5.dom.Element;
019 import org.apache.tapestry5.internal.services.PageRenderQueue;
020 import org.apache.tapestry5.json.JSONObject;
021 import org.apache.tapestry5.runtime.RenderCommand;
022 import org.apache.tapestry5.runtime.RenderQueue;
023 import org.apache.tapestry5.services.PartialMarkupRenderer;
024 import org.apache.tapestry5.services.PartialMarkupRendererFilter;
025
026 /**
027 * Responsible for capturing the content for a single zone and storing it into the JSON reply object. As a {@link PartialMarkupRendererFilter} , this
028 * has access to the {@link JSONObject} for the reply, and can {@linkplain PageRenderQueue#addPartialRenderer(org.apache.tapestry5.runtime.RenderCommand) add renderers that generate and package the markup content}.
029 *
030 * @see org.apache.tapestry5.ajax.MultiZoneUpdate
031 * @see org.apache.tapestry5.services.ajax.AjaxResponseRenderer#addRender(String, Object)
032 * @since 5.1.0.1
033 */
034 public class SingleZonePartialRendererFilter implements PartialMarkupRendererFilter
035 {
036 private final String zoneId;
037
038 private final RenderCommand zoneRenderCommand;
039
040 private final PageRenderQueue queue;
041
042 private final AjaxFormUpdateController ajaxFormUpdateController;
043
044 public SingleZonePartialRendererFilter(String zoneId, RenderCommand zoneRenderCommand, PageRenderQueue queue,
045 AjaxFormUpdateController ajaxFormUpdateController)
046 {
047 this.zoneId = zoneId;
048 this.zoneRenderCommand = zoneRenderCommand;
049 this.queue = queue;
050 this.ajaxFormUpdateController = ajaxFormUpdateController;
051 }
052
053 public void renderMarkup(MarkupWriter writer, final JSONObject reply, PartialMarkupRenderer renderer)
054 {
055 RenderCommand forZone = new RenderCommand()
056 {
057 public void render(MarkupWriter writer, RenderQueue queue)
058 {
059 // Create an element to contain the content for the zone. We give it a mnemonic
060 // element name and attribute just to help with debugging (the element itself is discarded).
061
062 final Element zoneContainer = writer.element("zone-update", "zoneId", zoneId);
063
064 ajaxFormUpdateController.setupBeforePartialZoneRender(writer);
065
066 queue.push(new RenderCommand()
067 {
068 public void render(MarkupWriter writer, RenderQueue queue)
069 {
070 writer.end(); // the zoneContainer element
071
072 // Need to do this Ajax Form-related cleanup here, before we extract the zone content.
073
074 ajaxFormUpdateController.cleanupAfterPartialZoneRender();
075
076 String zoneUpdateContent = zoneContainer.getChildMarkup();
077
078 zoneContainer.remove();
079
080 if (!reply.has("zones"))
081 {
082 reply.put("zones", new JSONObject());
083 }
084
085 reply.getJSONObject("zones").put(zoneId, zoneUpdateContent);
086 }
087 });
088
089 // Make sure the zone's actual rendering command is processed first, then the inline
090 // RenderCommand just above.
091
092 queue.push(zoneRenderCommand);
093 }
094 };
095
096 queue.addPartialRenderer(forZone);
097
098 renderer.renderMarkup(writer, reply);
099 }
100 }