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}