001// Licensed under the Apache License, Version 2.0 (the "License"); 002// you may not use this file except in compliance with the License. 003// You may obtain a copy of the License at 004// 005// http://www.apache.org/licenses/LICENSE-2.0 006// 007// Unless required by applicable law or agreed to in writing, software 008// distributed under the License is distributed on an "AS IS" BASIS, 009// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 010// See the License for the specific language governing permissions and 011// limitations under the License. 012 013package org.apache.tapestry5.ajax; 014 015import org.apache.tapestry5.ClientBodyElement; 016import org.apache.tapestry5.ioc.internal.util.CollectionFactory; 017import org.apache.tapestry5.ioc.internal.util.InternalUtils; 018 019import java.util.Map; 020 021/** 022 * A mapping from <em>client-side zone ids</em> to objects that can render the content for that zone on the client. An 023 * event handler method may instantiate an instance and chain together a series of calls to {@link #add(String, Object)} 024 * , and return the final result. 025 * 026 * Remember that client-side element ids may not match server-side component ids, especially once Ajax is added to the 027 * mix. Because of this, it is highly recommended that the client-side logic gather the actual component ids and include 028 * those in the Ajax request, to ensure that the server generates updates that the client can process. Better yet, use 029 * the Zone's id parameter to lock down the zone's id to a known, predictable value. 030 * 031 * @since 5.1.0.1 032 * @deprecated Deprecated in 5.3; use the {@link org.apache.tapestry5.services.ajax.AjaxResponseRenderer} service instead of 033 * returning an instance of MultiZoneUpdate 034 */ 035public class MultiZoneUpdate 036{ 037 private final MultiZoneUpdate parent; 038 039 private final String zoneId; 040 041 private final Object renderer; 042 043 public MultiZoneUpdate(String zoneId, Object renderer) 044 { 045 this(zoneId, renderer, null); 046 } 047 048 /** 049 * Alternate constructor that takes a ClientBodyElement (typically, a 050 * {@link org.apache.tapestry5.corelib.components.Zone}). 051 */ 052 public MultiZoneUpdate(ClientBodyElement zone) 053 { 054 this(zone.getClientId(), zone.getBody()); 055 } 056 057 private MultiZoneUpdate(String zoneId, Object renderer, MultiZoneUpdate parent) 058 { 059 assert renderer != null; 060 assert InternalUtils.isNonBlank(zoneId); 061 062 this.zoneId = zoneId; 063 this.renderer = renderer; 064 this.parent = parent; 065 } 066 067 /** 068 * Adds the zone (represented by the {@link ClientBodyElement}) to the update. 069 * 070 * @since 5.2.3 071 */ 072 public MultiZoneUpdate add(ClientBodyElement zone) 073 { 074 assert zone != null; 075 076 return add(zone.getClientId(), zone.getBody()); 077 } 078 079 /** 080 * Returns a <strong>new</strong> MultiZoneUpdate reflecting the mapping from the indicated zone to an object that 081 * will render the content for that zone. 082 * 083 * @param zoneId client id of zone to update 084 * @param renderer object that can provide the content for the zone 085 * @return new MultiZoneUpdate 086 */ 087 public MultiZoneUpdate add(String zoneId, Object renderer) 088 { 089 return new MultiZoneUpdate(zoneId, renderer, this); 090 } 091 092 /** 093 * Returns a mapping from client zone id to renderer object for that zone. 094 * 095 * @return string to renderer map 096 */ 097 public Map<String, Object> getZoneToRenderMap() 098 { 099 Map<String, Object> result = CollectionFactory.newMap(); 100 101 MultiZoneUpdate cursor = this; 102 103 while (cursor != null) 104 { 105 result.put(cursor.zoneId, cursor.renderer); 106 107 cursor = cursor.parent; 108 } 109 110 return result; 111 } 112 113 @Override 114 public String toString() 115 { 116 return String.format("MultiZoneUpdate[%s]", getZoneToRenderMap()); 117 } 118}