001 // Copyright 2009, 2010 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.ajax; 016 017 import org.apache.tapestry5.ClientBodyElement; 018 import org.apache.tapestry5.ioc.internal.util.CollectionFactory; 019 import org.apache.tapestry5.ioc.internal.util.InternalUtils; 020 021 import java.util.Map; 022 023 /** 024 * A mapping from <em>client-side zone ids</em> to objects that can render the content for that zone on the client. An 025 * event handler method may instantiate an instance and chain together a series of calls to {@link #add(String, Object)} 026 * , and return the final result. 027 * <p/> 028 * Remember that client-side element ids may not match server-side component ids, especially once Ajax is added to the 029 * mix. Because of this, it is highly recommended that the client-side logic gather the actual component ids and include 030 * those in the Ajax request, to ensure that the server generates updates that the client can process. Better yet, use 031 * the Zone's id parameter to lock down the zone's id to a known, predictable value. 032 * 033 * @since 5.1.0.1 034 * @deprecated Deprecated in 5.3; use the {@link org.apache.tapestry5.services.ajax.AjaxResponseRenderer} service instead of 035 * returning an instance of MultiZoneUpdate 036 */ 037 public class MultiZoneUpdate 038 { 039 private final MultiZoneUpdate parent; 040 041 private final String zoneId; 042 043 private final Object renderer; 044 045 public MultiZoneUpdate(String zoneId, Object renderer) 046 { 047 this(zoneId, renderer, null); 048 } 049 050 /** 051 * Alternate constructor that takes a ClientBodyElement (typically, a 052 * {@link org.apache.tapestry5.corelib.components.Zone}). 053 */ 054 public MultiZoneUpdate(ClientBodyElement zone) 055 { 056 this(zone.getClientId(), zone.getBody()); 057 } 058 059 private MultiZoneUpdate(String zoneId, Object renderer, MultiZoneUpdate parent) 060 { 061 assert renderer != null; 062 assert InternalUtils.isNonBlank(zoneId); 063 064 this.zoneId = zoneId; 065 this.renderer = renderer; 066 this.parent = parent; 067 } 068 069 /** 070 * Adds the zone (represented by the {@link ClientBodyElement}) to the update. 071 * 072 * @since 5.2.3 073 */ 074 public MultiZoneUpdate add(ClientBodyElement zone) 075 { 076 assert zone != null; 077 078 return add(zone.getClientId(), zone.getBody()); 079 } 080 081 /** 082 * Returns a <strong>new</strong> MultiZoneUpdate reflecting the mapping from the indicated zone to an object that 083 * will render the content for that zone. 084 * 085 * @param zoneId client id of zone to update 086 * @param renderer object that can provide the content for the zone 087 * @return new MultiZoneUpdate 088 */ 089 public MultiZoneUpdate add(String zoneId, Object renderer) 090 { 091 return new MultiZoneUpdate(zoneId, renderer, this); 092 } 093 094 /** 095 * Returns a mapping from client zone id to renderer object for that zone. 096 * 097 * @return string to renderer map 098 */ 099 public Map<String, Object> getZoneToRenderMap() 100 { 101 Map<String, Object> result = CollectionFactory.newMap(); 102 103 MultiZoneUpdate cursor = this; 104 105 while (cursor != null) 106 { 107 result.put(cursor.zoneId, cursor.renderer); 108 109 cursor = cursor.parent; 110 } 111 112 return result; 113 } 114 115 @Override 116 public String toString() 117 { 118 return String.format("MultiZoneUpdate[%s]", getZoneToRenderMap()); 119 } 120 }