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 }