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.http.services.Request;
019import org.apache.tapestry5.ioc.services.PerThreadValue;
020import org.apache.tapestry5.ioc.services.PerthreadManager;
021import org.apache.tapestry5.services.ApplicationStateManager;
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        alert(duration, severity, message, false);
068    }
069
070    public void alert(Duration duration, Severity severity, String message, boolean markup)
071    {
072        final Alert alert = new Alert(duration, severity, message, markup);
073
074        if (request.isXHR())
075        {
076            addCallbackForAlert(alert);
077        }
078
079        // Add it to the storage; this is always done, even in an Ajax request, because we may end up
080        // redirecting to a new page, rather than doing a partial page update on the current page ... in which
081        // case we need the alerts stored persistently until we render the new page.
082
083        getAlertStorage().add(alert);
084    }
085
086    private void addCallbackForAlert(final Alert alert)
087    {
088        ajaxResponseRenderer.addCallback(new JavaScriptCallback()
089        {
090            public void run(JavaScriptSupport javascriptSupport)
091            {
092                javascriptSupport.require("t5/core/alert").with(alert.toJSON());
093            }
094        });
095
096        addAlertStorageCleanupCallback();
097    }
098
099    private void addAlertStorageCleanupCallback()
100    {
101        // Add a callback that exists just to clear the non-persistent alerts.
102        // Only one of these is needed.
103
104        if (needAlertStorageCleanup.get(true))
105        {
106            ajaxResponseRenderer.addCallback(new JavaScriptCallback()
107            {
108                public void run(JavaScriptSupport javascriptSupport)
109                {
110                    // In an Ajax request, the Alerts are added, just so that they can be removed if not persistent.
111                    // Again, this is for the rare case where there's a redirect to another page.
112
113                    getAlertStorage().dismissNonPersistent();
114                }
115            });
116
117            needAlertStorageCleanup.set(false);
118        }
119    }
120
121    private AlertStorage getAlertStorage()
122    {
123        return asm.get(AlertStorage.class);
124    }
125
126}