001    // Copyright 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.alerts;
016    
017    import org.apache.tapestry5.alerts.*;
018    import org.apache.tapestry5.ioc.services.PerThreadValue;
019    import org.apache.tapestry5.ioc.services.PerthreadManager;
020    import org.apache.tapestry5.services.ApplicationStateManager;
021    import org.apache.tapestry5.services.Request;
022    import org.apache.tapestry5.services.ajax.AjaxResponseRenderer;
023    import org.apache.tapestry5.services.ajax.JavaScriptCallback;
024    import org.apache.tapestry5.services.javascript.JavaScriptSupport;
025    
026    public class AlertManagerImpl implements AlertManager
027    {
028        private final ApplicationStateManager asm;
029    
030        private final Request request;
031    
032        private final AjaxResponseRenderer ajaxResponseRenderer;
033    
034        private final PerThreadValue<Boolean> needAlertStorageCleanup;
035    
036        public AlertManagerImpl(ApplicationStateManager asm, Request request, AjaxResponseRenderer ajaxResponseRenderer, PerthreadManager perThreadManager)
037        {
038            this.asm = asm;
039            this.request = request;
040            this.ajaxResponseRenderer = ajaxResponseRenderer;
041    
042            needAlertStorageCleanup = perThreadManager.createValue();
043        }
044    
045        public void info(String message)
046        {
047            alert(Duration.SINGLE, Severity.INFO, message);
048        }
049    
050        public void warn(String message)
051        {
052            alert(Duration.SINGLE, Severity.WARN, message);
053        }
054    
055        public void error(String message)
056        {
057            alert(Duration.SINGLE, Severity.ERROR, message);
058        }
059    
060        public void alert(Duration duration, Severity severity, String message)
061        {
062            final Alert alert = new Alert(duration, severity, message);
063    
064            if (request.isXHR())
065            {
066                addCallbackForAlert(alert);
067            }
068    
069            // Add it to the storage; this is always done, even in an Ajax request, because we may end up
070            // redirecting to a new page, rather than doing a partial page update on the current page ... in which
071            // case we need the alerts stored persistently until we render the new page.
072    
073            getAlertStorage().add(alert);
074        }
075    
076        private void addCallbackForAlert(final Alert alert)
077        {
078            ajaxResponseRenderer.addCallback(new JavaScriptCallback()
079            {
080                public void run(JavaScriptSupport javascriptSupport)
081                {
082                    javascriptSupport.addInitializerCall("addAlert", alert.toJSON());
083                }
084            });
085    
086            addAlertStorageCleanupCallback();
087        }
088    
089        private void addAlertStorageCleanupCallback()
090        {
091            // Add a callback that exists just to clear the non-persistent alerts.
092            // Only one of these is needed.
093    
094            if (needAlertStorageCleanup.get(true))
095            {
096                ajaxResponseRenderer.addCallback(new JavaScriptCallback()
097                {
098                    public void run(JavaScriptSupport javascriptSupport)
099                    {
100                        // In an Ajax request, the Alerts are added, just so that they can be removed if not persistent.
101                        // Again, this is for the rare case where there's a redirect to another page.
102    
103                        getAlertStorage().dismissNonPersistent();
104                    }
105                });
106    
107                needAlertStorageCleanup.set(false);
108            }
109        }
110    
111        private AlertStorage getAlertStorage()
112        {
113            return asm.get(AlertStorage.class);
114        }
115    
116    }