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 success(String message)
046        {
047            alert(Duration.SINGLE, Severity.SUCCESS, message);
048        }
049        
050        public void info(String message)
051        {
052            alert(Duration.SINGLE, Severity.INFO, message);
053        }
054    
055        public void warn(String message)
056        {
057            alert(Duration.SINGLE, Severity.WARN, message);
058        }
059    
060        public void error(String message)
061        {
062            alert(Duration.SINGLE, Severity.ERROR, message);
063        }
064    
065        public void alert(Duration duration, Severity severity, String message)
066        {
067            final Alert alert = new Alert(duration, severity, message);
068    
069            if (request.isXHR())
070            {
071                addCallbackForAlert(alert);
072            }
073    
074            // Add it to the storage; this is always done, even in an Ajax request, because we may end up
075            // redirecting to a new page, rather than doing a partial page update on the current page ... in which
076            // case we need the alerts stored persistently until we render the new page.
077    
078            getAlertStorage().add(alert);
079        }
080    
081        private void addCallbackForAlert(final Alert alert)
082        {
083            ajaxResponseRenderer.addCallback(new JavaScriptCallback()
084            {
085                public void run(JavaScriptSupport javascriptSupport)
086                {
087                    javascriptSupport.addInitializerCall("addAlert", alert.toJSON());
088                }
089            });
090    
091            addAlertStorageCleanupCallback();
092        }
093    
094        private void addAlertStorageCleanupCallback()
095        {
096            // Add a callback that exists just to clear the non-persistent alerts.
097            // Only one of these is needed.
098    
099            if (needAlertStorageCleanup.get(true))
100            {
101                ajaxResponseRenderer.addCallback(new JavaScriptCallback()
102                {
103                    public void run(JavaScriptSupport javascriptSupport)
104                    {
105                        // In an Ajax request, the Alerts are added, just so that they can be removed if not persistent.
106                        // Again, this is for the rare case where there's a redirect to another page.
107    
108                        getAlertStorage().dismissNonPersistent();
109                    }
110                });
111    
112                needAlertStorageCleanup.set(false);
113            }
114        }
115    
116        private AlertStorage getAlertStorage()
117        {
118            return asm.get(AlertStorage.class);
119        }
120    
121    }