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    }