2
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
6
* The contents of this file are subject to the terms of either the GNU
7
* General Public License Version 2 only ("GPL") or the Common
8
* Development and Distribution License("CDDL") (collectively, the
9
* "License"). You may not use this file except in compliance with the
10
* License. You can obtain a copy of the License at
11
* http://www.netbeans.org/cddl-gplv2.html
12
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
* specific language governing permissions and limitations under the
14
* License. When distributing the software, include this License Header
15
* Notice in each file and include the License file at
16
* nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
17
* particular file as subject to the "Classpath" exception as provided
18
* by Sun in the GPL Version 2 section of the License file that
19
* accompanied this code. If applicable, add the following below the
20
* License Header, with the fields enclosed by brackets [] replaced by
21
* your own identifying information:
22
* "Portions Copyrighted [year] [name of copyright owner]"
26
* The Original Software is NetBeans. The Initial Developer of the Original
27
* Software is Sun Microsystems, Inc. Portions Copyright 2004 Sun
28
* Microsystems, Inc. All Rights Reserved.
30
* If you wish your version of this file to be governed by only the CDDL
31
* or only the GPL Version 2, indicate your decision by adding
32
* "[Contributor] elects to include this software in this distribution
33
* under the [CDDL or GPL Version 2] license." If you do not indicate a
34
* single choice of license, a recipient has the option to distribute
35
* your version of this file under either the CDDL, the GPL Version 2 or
36
* to extend the choice of license to its licensees as provided above.
37
* However, if you add GPL Version 2 code and therefore, elected the GPL
38
* Version 2 license, then the option applies only if the new code is
39
* made subject to such option by the copyright holder.
42
package org.netbeans.modules.junit;
45
* Manager of layered messages.
46
* It serves for management of messages layered over. When a message is to be
47
* displayed, it is put into a certain layer. When there is another message
48
* set in an upper layer, the topmost message does not change. Conversely,
49
* when the topmost message is cleared, another message becomes the topmost
50
* message and needs to be displayed. This class handles all these changes
51
* and returns information what message needs to be displayed after each
52
* addition/removal of message.
54
* The stack has a fixed number of layers
55
* (specified by calling the constructor). Each layer has its number,
56
* beginning with <code>0</code> (the topmost layer) and ending with
57
* <code><var>n</var> - 1</code> where <code><var>n</var></code>
58
* is the number of layers.
60
* There is one special layer for displaying volatile messages.
61
* Volatile messages are those messages that are always displayed
62
* on the top of all other messages but are cleared/overwritten
63
* as soon as another message is to be displayed.
66
* @author Marian Petras
68
public final class MessageStack {
71
* The class is final only for performance reasons.
74
/** layer number of the special layer for volatile messages */
75
public static final int LAYER_VOLATILE = -1;
78
* messages in layers (index <code>0</code> means the topmost layer)
80
private final String[] messageLayers;
82
* index of the visible (topmost non-empty) layer.
83
* If the stack is empty, it has value <code>-1</code>.
85
private int visibleLayerIndex = -1;
86
/** currently displayed volatile message (or <code>null</code>) */
87
private String volatileMsg;
90
* Creates a new <code>MessageStack</code> with a given number of layers.
92
* @param size number of layers in the stack
94
public MessageStack(int size) {
96
throw new IllegalArgumentException(
97
"number of layers must be positive"); //NOI18N
99
messageLayers = new String[size];
103
* Returns the currently "displayed" message.
105
* @return message that should be currently displayed according to
106
* performed display modifications;
107
* or <code>null</code> if no message should be displayed
109
public String getDisplayedMessage() {
110
return volatileMsg != null ? volatileMsg
111
: getTopmostStackMessage();
115
* Returns the topmost message on the stack.
117
* @return the topmost non-empty message on the stack;
118
* or <code>null</code> if the stack is empty
120
private String getTopmostStackMessage() {
121
return visibleLayerIndex != -1 ? messageLayers[visibleLayerIndex]
126
* Clears this message stack.
127
* After cleaning, both volatile message and all of the stack messages
130
public void clear() {
132
if (visibleLayerIndex != -1) {
133
for (int i = visibleLayerIndex; i < messageLayers.length; i++) {
134
messageLayers[i] = null;
136
visibleLayerIndex = -1;
141
* Puts a message on the given layer of the stack.
142
* Putting a message on the special layer for volatile messages
143
* (layer number <code>LAYER_VOLATILE</code>) has the same effect
144
* as calling {@link #setVolatileMessage(String)}.
146
* @param layer layer number
147
* @param message message to be displayed, or <code>null</code>
148
* if the existing message should be removed from the layer
149
* @return message that needs to be displayed in order to show the topmost
150
* message of the (updated) stack, or <code>null</code> if no
151
* change of display is necessary
152
* @exception java.lang.IllegalArgumentException
153
* if value of the <code>msgType</code> parameter is illegal
155
public String setMessage(final int layer, String message)
156
throws IllegalArgumentException {
158
/* check parameters: */
159
if (layer == LAYER_VOLATILE) {
160
return setVolatileMessage(message);
162
if (layer < 0 || layer >= messageLayers.length) {
163
throw new IllegalArgumentException(
164
java.text.MessageFormat.format(
165
"Message type out of bounds (0 .. {1}): {0}", //NOI18N
166
new Object[] { new Integer(layer),
167
new Integer(messageLayers.length) }));
170
/* unify parameters: */
171
if ((message != null) && (message.trim().length() == 0)) {
175
final String oldDisplayed = getDisplayedMessage();
177
/* update the register of messages: */
179
messageLayers[layer] = message;
181
/* update the visible layer index: */
182
if (message != null) {
183
if ((visibleLayerIndex == -1) || (layer < visibleLayerIndex)) {
184
visibleLayerIndex = layer;
186
} else if (layer == visibleLayerIndex) {
187
for (int i = layer + 1; i < messageLayers.length; i++) {
188
if (messageLayers[i] != null) {
189
visibleLayerIndex = i;
193
if (visibleLayerIndex == layer) { //no visible layer found
194
visibleLayerIndex = -1;
198
/* compare the old and new display: */
199
return checkDisplayModified(oldDisplayed, getDisplayedMessage());
203
* Clears a message on the given layer of the stack.
204
* Calling this method has the same effect as calling
205
* <code>setMessage(layer, null)</code> (on the same layer).
207
* @param layer layer number
208
* @return message that needs to be displayed in order to show the topmost
209
* message of the (updated) stack, or <code>null</code> if no
210
* change of display is necessary
213
public String clearMessage(final int layer) {
214
return setMessage(layer, null);
218
* Displays a volatile message on top of all existing messages.
220
* @param message to be displayed, or <code>null</code>
221
* if the previous volatile message should be removed
222
* @return message that needs to be displayed in order to show the message
223
* on the top of the stack, or <code>null</code> if no change
224
* of display is necessary
226
public String setVolatileMessage(String message) {
228
/* unify parameters: */
229
if ((message != null) && (message.trim().length() == 0)) {
233
final String oldDisplayed = getDisplayedMessage();
235
/* update the register of messages: */
236
volatileMsg = message;
238
/* compare the old and new display: */
239
return checkDisplayModified(oldDisplayed, getDisplayedMessage());
243
* Clears the previous volatile message (if any).
244
* Calling this method has the same effect as calling
245
* <code>setVolatileMessage(null)</code>.
247
* @return message that needs to be displayed in order to show the message
248
* on the top of the stack or an empty string
249
* (<code>""</code>) if no message should be displayed
250
* @see #setVolatileMessage
252
public String clearVolatileMessage() {
253
return setVolatileMessage(null);
257
* Compares the previous and the new displayed message.
259
* @return <code>null</code> if both messages are the same (possibly empty),
260
* an empty string (<code>""</code>) if the previous
261
* message was non-empty and the new message is empty,
262
* or the new message if it is non-empty and different from
265
private String checkDisplayModified(String oldDisplay, String newDisplay) {
266
if ((newDisplay == null) && (oldDisplay != null)) {
269
if ((newDisplay != null) && !newDisplay.equals(oldDisplay)) {