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
015package org.apache.tapestry5.internal.alerts;
016
017import org.apache.tapestry5.alerts.*;
018import org.apache.tapestry5.ioc.services.PerThreadValue;
019import org.apache.tapestry5.ioc.services.PerthreadManager;
020import org.apache.tapestry5.services.ApplicationStateManager;
021import org.apache.tapestry5.services.Request;
022import org.apache.tapestry5.services.ajax.AjaxResponseRenderer;
023import org.apache.tapestry5.services.ajax.JavaScriptCallback;
024import org.apache.tapestry5.services.javascript.JavaScriptSupport;
025
026public 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}