001// Copyright 2011, 2013, 2014 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 final String clientId = zone.getClientId(); 067 068 if (clientId == null) 069 { 070 throw new IllegalArgumentException( 071 "Attempt to render a ClientBodyElement, probably a Zone, with a null clientId. " 072 + "You can solve this by using the id parameter."); 073 } 074 075 addRender(clientId, zone.getBody()); 076 077 return this; 078 } 079 080 public AjaxResponseRenderer addCallback(final JavaScriptCallback callback) 081 { 082 assert callback != null; 083 084 addFilter(new PartialMarkupRendererFilter() 085 { 086 public void renderMarkup(MarkupWriter writer, JSONObject reply, PartialMarkupRenderer renderer) 087 { 088 renderer.renderMarkup(writer, reply); 089 090 callback.run(javaScriptSupport); 091 } 092 }); 093 094 return this; 095 } 096 097 public AjaxResponseRenderer addCallback(final Runnable callback) 098 { 099 assert callback != null; 100 101 addFilter(new PartialMarkupRendererFilter() 102 { 103 public void renderMarkup(MarkupWriter writer, JSONObject reply, PartialMarkupRenderer renderer) 104 { 105 renderer.renderMarkup(writer, reply); 106 107 callback.run(); 108 } 109 }); 110 111 112 return this; 113 } 114 115 private boolean isRedirect(JSONObject reply) 116 { 117 118 return reply.has(InternalConstants.PARTIAL_KEY) && 119 reply.in(InternalConstants.PARTIAL_KEY).has("redirectURL"); 120 } 121 122 public AjaxResponseRenderer addFilter(final PartialMarkupRendererFilter filter) 123 { 124 assert filter != null; 125 126 queue.addPartialMarkupRendererFilter(new PartialMarkupRendererFilter() 127 { 128 public void renderMarkup(MarkupWriter writer, JSONObject reply, PartialMarkupRenderer delete) 129 { 130 if (isRedirect(reply)) 131 { 132 // Bypass the callback. 133 delete.renderMarkup(writer, reply); 134 return; 135 } 136 137 filter.renderMarkup(writer, reply, delete); 138 } 139 }); 140 141 return this; 142 } 143 144 public AjaxResponseRenderer addCallback(final JSONCallback callback) 145 { 146 assert callback != null; 147 148 addFilter(new PartialMarkupRendererFilter() 149 { 150 public void renderMarkup(MarkupWriter writer, JSONObject reply, PartialMarkupRenderer renderer) 151 { 152 renderer.renderMarkup(writer, reply); 153 154 callback.run(reply); 155 } 156 }); 157 158 return this; 159 } 160}