    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    }