001// Copyright 2009-2012 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 015package org.apache.tapestry5.internal.services.ajax; 016 017import org.apache.tapestry5.MarkupWriter; 018import org.apache.tapestry5.dom.Element; 019import org.apache.tapestry5.internal.InternalConstants; 020import org.apache.tapestry5.internal.services.PageRenderQueue; 021import org.apache.tapestry5.json.JSONArray; 022import org.apache.tapestry5.json.JSONObject; 023import org.apache.tapestry5.runtime.RenderCommand; 024import org.apache.tapestry5.runtime.RenderQueue; 025import org.apache.tapestry5.services.PartialMarkupRenderer; 026import org.apache.tapestry5.services.PartialMarkupRendererFilter; 027 028/** 029 * Responsible for capturing the content for a single zone and storing it into the JSON reply object. As a {@link PartialMarkupRendererFilter} , this 030 * 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}. 031 * 032 * @see org.apache.tapestry5.ajax.MultiZoneUpdate 033 * @see org.apache.tapestry5.services.ajax.AjaxResponseRenderer#addRender(String, Object) 034 * @since 5.1.0.1 035 */ 036public class SingleZonePartialRendererFilter implements PartialMarkupRendererFilter 037{ 038 private final String zoneId; 039 040 private final RenderCommand zoneRenderCommand; 041 042 private final PageRenderQueue queue; 043 044 private final AjaxFormUpdateController ajaxFormUpdateController; 045 046 public SingleZonePartialRendererFilter(String zoneId, RenderCommand zoneRenderCommand, PageRenderQueue queue, 047 AjaxFormUpdateController ajaxFormUpdateController) 048 { 049 this.zoneId = zoneId; 050 this.zoneRenderCommand = zoneRenderCommand; 051 this.queue = queue; 052 this.ajaxFormUpdateController = ajaxFormUpdateController; 053 } 054 055 public void renderMarkup(MarkupWriter writer, final JSONObject reply, PartialMarkupRenderer renderer) 056 { 057 RenderCommand forZone = new RenderCommand() 058 { 059 public void render(MarkupWriter writer, RenderQueue queue) 060 { 061 // Create an element to contain the content for the zone. We give it a mnemonic 062 // element name and attribute just to help with debugging (the element itself is discarded). 063 064 final Element zoneContainer = writer.element("zone-update", "zoneId", zoneId); 065 066 ajaxFormUpdateController.setupBeforePartialZoneRender(writer); 067 068 queue.push(new RenderCommand() 069 { 070 public void render(MarkupWriter writer, RenderQueue queue) 071 { 072 writer.end(); // the zoneContainer element 073 074 // Need to do this Ajax Form-related cleanup here, before we extract the zone content. 075 076 ajaxFormUpdateController.cleanupAfterPartialZoneRender(); 077 078 String zoneUpdateContent = zoneContainer.getChildMarkup(); 079 080 zoneContainer.remove(); 081 082 // This has changed a bit in 5.4; 083 // In 5.3, it was just "zones", and was key/value pairs for id and content. 084 // In 5.4, it is "content", and is an array of id/content arrays 085 reply.in(InternalConstants.PARTIAL_KEY).append("content", 086 new JSONArray(zoneId, zoneUpdateContent)); 087 } 088 }); 089 090 // Make sure the zone's actual rendering command is processed first, then the inline 091 // RenderCommand just above. 092 093 queue.push(zoneRenderCommand); 094 } 095 }; 096 097 queue.addPartialRenderer(forZone); 098 099 renderer.renderMarkup(writer, reply); 100 } 101}