    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.ajax.MultiZoneUpdate;
    018    import org.apache.tapestry5.internal.services.AjaxPartialResponseRenderer;
    019    import org.apache.tapestry5.ioc.internal.util.InternalUtils;
    020    import org.apache.tapestry5.ioc.services.TypeCoercer;
    021    import org.apache.tapestry5.runtime.RenderCommand;
    022    import org.apache.tapestry5.services.ComponentEventResultProcessor;
    023    import org.apache.tapestry5.services.ajax.AjaxResponseRenderer;
    024
    025    import java.io.IOException;
    026    import java.util.Map;
    027
    028    /**
    029     * Handler for {@link org.apache.tapestry5.ajax.MultiZoneUpdate} responses from a component event handler method. Works
    030     * by adding {@link SingleZonePartialRendererFilter}s for each zone to the
    031     * {@linkplain org.apache.tapestry5.internal.services.PageRenderQueue#addPartialMarkupRendererFilter(org.apache.tapestry5.services.PartialMarkupRendererFilter)
    032     * filter stack}. Each zone writes its content as a string in the zones object of the reply, keyed on its id.
    033     * JavaScript and CSS are collected for all zones rendered in the request (not for each individual zone). The final
    034     * response will have some combination of "script", "scripts", "stylesheets", "content" (which is expected to be blank)
    035     * and "zones".
    036     *
    037     * @since 5.1.0.1
    038     * @deprecated Deprecated in 5.3
    039     */
    040    public class MultiZoneUpdateEventResultProcessor implements ComponentEventResultProcessor<MultiZoneUpdate>
    041    {
    042        private final TypeCoercer typeCoercer;
    043
    044        private final AjaxResponseRenderer ajaxResponseRenderer;
    045
    046        private final AjaxPartialResponseRenderer partialRenderer;
    047
    048        public MultiZoneUpdateEventResultProcessor(TypeCoercer typeCoercer, AjaxResponseRenderer ajaxResponseRenderer, AjaxPartialResponseRenderer partialRenderer)
    049        {
    050            this.typeCoercer = typeCoercer;
    051            this.ajaxResponseRenderer = ajaxResponseRenderer;
    052            this.partialRenderer = partialRenderer;
    053        }
    054
    055        public void processResultValue(final MultiZoneUpdate value) throws IOException
    056        {
    057
    058            Map<String, Object> map = value.getZoneToRenderMap();
    059
    060            for (String zoneId : map.keySet())
    061            {
    062                Object provided = map.get(zoneId);
    063
    064                // The AjaxResponseRenderer will convert the object to a RenderCommand, but does nothing special if there's a failure
    065                // (because the stack trace will clearly identify what's going on). We do the conversion here so that we can relate
    066                // a failure to a zone id. It will just be a pass-thru on the second type coercion.
    067
    068                RenderCommand zoneRenderCommand = toRenderer(zoneId, provided);
    069
    070                ajaxResponseRenderer.addRender(zoneId, zoneRenderCommand);
    071            }
    072
    073            partialRenderer.renderPartialPageMarkup();
    074        }
    075
    076        private RenderCommand toRenderer(String zoneId, Object provided)
    077        {
    078            try
    079            {
    080                return typeCoercer.coerce(provided, RenderCommand.class);
    081            } catch (Exception ex)
    082            {
    083                throw new IllegalArgumentException(String.format("Failure converting renderer for zone '%s': %s", zoneId,
    084                        InternalUtils.toMessage(ex)), ex);
    085            }
    086        }
    087    }