001//  Copyright 2011, 2013 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
014package org.apache.tapestry5.internal.services.ajax;
015
016import org.apache.tapestry5.ClientBodyElement;
017import org.apache.tapestry5.MarkupWriter;
018import org.apache.tapestry5.internal.InternalConstants;
019import org.apache.tapestry5.internal.services.PageRenderQueue;
020import org.apache.tapestry5.ioc.internal.util.InternalUtils;
021import org.apache.tapestry5.ioc.services.TypeCoercer;
022import org.apache.tapestry5.json.JSONObject;
023import org.apache.tapestry5.runtime.RenderCommand;
024import org.apache.tapestry5.services.PartialMarkupRenderer;
025import org.apache.tapestry5.services.PartialMarkupRendererFilter;
026import org.apache.tapestry5.services.ajax.AjaxResponseRenderer;
027import org.apache.tapestry5.services.ajax.JSONCallback;
028import org.apache.tapestry5.services.ajax.JavaScriptCallback;
029import org.apache.tapestry5.services.javascript.JavaScriptSupport;
030
031
032public class AjaxResponseRendererImpl implements AjaxResponseRenderer
033{
034    private final PageRenderQueue queue;
035
036    private final AjaxFormUpdateController ajaxFormUpdateController;
037
038    private final TypeCoercer typeCoercer;
039
040    private final JavaScriptSupport javaScriptSupport;
041
042    public AjaxResponseRendererImpl(PageRenderQueue queue, AjaxFormUpdateController ajaxFormUpdateController, TypeCoercer typeCoercer, JavaScriptSupport javaScriptSupport)
043    {
044        this.queue = queue;
045        this.ajaxFormUpdateController = ajaxFormUpdateController;
046        this.typeCoercer = typeCoercer;
047        this.javaScriptSupport = javaScriptSupport;
048    }
049
050    public AjaxResponseRenderer addRender(String clientId, Object renderer)
051    {
052        assert InternalUtils.isNonBlank(clientId);
053        assert renderer != null;
054
055        RenderCommand command = typeCoercer.coerce(renderer, RenderCommand.class);
056
057        addFilter(new SingleZonePartialRendererFilter(clientId, command, queue, ajaxFormUpdateController));
058
059        return this;
060    }
061
062    public AjaxResponseRenderer addRender(ClientBodyElement zone)
063    {
064        assert zone != null;
065
066        addRender(zone.getClientId(), zone.getBody());
067
068        return this;
069    }
070
071    public AjaxResponseRenderer addCallback(final JavaScriptCallback callback)
072    {
073        assert callback != null;
074
075        addFilter(new PartialMarkupRendererFilter()
076        {
077            public void renderMarkup(MarkupWriter writer, JSONObject reply, PartialMarkupRenderer renderer)
078            {
079                renderer.renderMarkup(writer, reply);
080
081                callback.run(javaScriptSupport);
082            }
083        });
084
085        return this;
086    }
087
088    public AjaxResponseRenderer addCallback(final Runnable callback)
089    {
090        assert callback != null;
091
092        addFilter(new PartialMarkupRendererFilter()
093        {
094            public void renderMarkup(MarkupWriter writer, JSONObject reply, PartialMarkupRenderer renderer)
095            {
096                renderer.renderMarkup(writer, reply);
097
098                callback.run();
099            }
100        });
101
102
103        return this;
104    }
105
106    private boolean isRedirect(JSONObject reply)
107    {
108
109        return reply.has(InternalConstants.PARTIAL_KEY) &&
110                reply.in(InternalConstants.PARTIAL_KEY).has("redirectURL");
111    }
112
113    public AjaxResponseRenderer addFilter(final PartialMarkupRendererFilter filter)
114    {
115        assert filter != null;
116
117        queue.addPartialMarkupRendererFilter(new PartialMarkupRendererFilter()
118        {
119            public void renderMarkup(MarkupWriter writer, JSONObject reply, PartialMarkupRenderer delete)
120            {
121                if (isRedirect(reply))
122                {
123                    // Bypass the callback.
124                    delete.renderMarkup(writer, reply);
125                    return;
126                }
127
128                filter.renderMarkup(writer, reply, delete);
129            }
130        });
131
132        return this;
133    }
134
135    public AjaxResponseRenderer addCallback(final JSONCallback callback)
136    {
137        assert callback != null;
138
139        addFilter(new PartialMarkupRendererFilter()
140        {
141            public void renderMarkup(MarkupWriter writer, JSONObject reply, PartialMarkupRenderer renderer)
142            {
143                renderer.renderMarkup(writer, reply);
144
145                callback.run(reply);
146            }
147        });
148
149        return this;
150    }
151}