Friday, October 30, 2009

Section 2.2. Use Case Relationships










2.2. Use Case Relationships




A use case describes the way your system behaves to meet a requirement. When filling out your use case descriptions, you will notice that there is some similarity between steps in different use cases. You may also find that some use cases work in several different modes or special cases. Finally, you may also find a use case with multiple flows throughout its execution, and it would be good to show those important optional cases on your use case diagrams.


Wouldn't it be great if you could get rid of the repetition between use case descriptions and show important optional flows right on your use case diagrams? OK, so that was a loaded question. You can show reusable, optional, and even specialized use case behavior between use cases.



2.2.1. The <<include>> Relationship









So far, you have seen that use cases typically work with actors to capture a requirement. Relationships between use cases are more about breaking your system's behavior into manageable chunks than adding anything new to your system. The purpose of use case relationships is to provide your system's designers with some architectural guidance so they can efficiently break down the system's concerns into manageable pieces within the detailed system design.


In addition to blogs, a CMS can have any number of means for working with its content. One popular mechanism for maintaining documents is by creating a Wiki. Wikis allow online authors to create, edit, and link together web pages to create a web of related content, or a Wiki-web. A great example of a Wiki is available at http://www.Wikipedia.org.



Take another look at the Create a new Blog Account use case description shown in Table 2-2. The description seems simple enough, but suppose another requirement is added to the Content Management System.



Requirement A.2


The content management system shall allow an administrator to create a new personal Wiki, provided the personal details of the applying author are verified using the Author Credentials Database.




To capture Requirement A.2 a new use case needs to be added to the Content Management System, as shown in Figure 2-11.


Now that we have added the new use case to our model, it's time to fill out a detailed use case description (shown in Table 2-3). See Table 2-1 if you need to refresh your memory about the meaning of each of the details within a use case description.



Figure 2-11. A new requirement can often mean a new use case for the system, although it's not always a one-to-one mapping



Table 2-3. The detailed description for the "Create a new Personal Wiki" use case

Use case name

Create a new Personal Wiki

Related Requirements

Requirement A.2.

Goal In Context

A new or existing author requests a new personal Wiki from the Administrator.

Preconditions

The author has appropriate proof of identity.

Successful End Condition

A new personal Wiki is created for the author.

Failed End Condition

The application for a new personal Wiki is rejected.

Primary Actors

Administrator.

Secondary Actors

Author Credentials Database.

Trigger

The Administrator asks the CMS to create a new personal Wiki.

Main Flow

Step

Action

 

1

The Administrator asks the system to create a new personal Wiki.

 

2

The Administrator enters the author's details.

 

3

The author's details are verified using the Author Credentials Database.

 

4

The new personal Wiki is created.

 

5

A summary of the new personal Wiki's details are emailed to the author.

Extensions

Step

Branching Action

 

3.1

The Author Credentials Database does not verify the author's details.

 

3.2

The author's new personal Wiki application is rejected.



The first thing to notice is that we have some redundancy between the two use case descriptions (Tables 2-2 and 2-3). Both Create a new Blog Account and Create a new Personal Wiki need to check the applicant's credentials. Currently, this behavior is simply repeated between the two use case descriptions.


This repetitive behavior shared between two use cases is best separated and captured within a totally new use case. This new use case can then be reused by the Create a new Blog Account and Create a new Personal Wiki use cases using the <<include>> relationship (as shown in Figure 2-12).



Figure 2-12. The <<include>> relationship supports reuse between use cases



The <<include>> relationship declares that the use case at the head of the dotted arrow completely reuses all of the steps from the use case being included. In Figure 2-12, the Create a new Blog Account and Create a new Personal Wiki completely reuse all of the steps declared in the Check Identity use case.


You can also see in Figure 2-12 that the Check Identity use case is not directly connected to the Administrator actor; it picks this connection up from the use cases that include it. However, the connection to the Author Credentials Database is now solely owned by the Check Identity use case. A benefit of this change is that it emphasizes that the Check Identity use case is the only one that relies directly on a connection to the Author Contact Details Database actor.


To show the <<include>> relationship in your use case descriptions, you need to remove the redundant steps from the Create a new Blog Account and Create new Personal Wiki use case descriptions and instead use the Included Cases field and include::<use case name> syntax to indicate the use case where the reused steps reside, as shown in Tables 2-4 and 2-5.


Table 2-4. Showing <<include>> in a use case description using Included Cases and include::<use case name>

Use case name

Create a new Blog Account

Related Requirements

Requirement A.1.

Goal In Context

A new or existing author requests a new blog account from the Administrator.

Preconditions

The author has appropriate proof of identity.

Successful End Condition

A new blog account is created for the author.

Failed End Condition

The application for a new blog account is rejected.

Primary Actors

Administrator

Secondary Actors

None

Trigger

The Administrator asks the CMS to create a new blog account.

Included Cases

Check Identity

Main Flow

Step

Action

 

1

The Administrator asks the system to create a new blog account.

 

2

The Administrator selects an account type.

 

3

The Administrator enters the author's details.

 

4

include::Check Identity

The author's details are checked.

 

5

The new account is created.

 

6

A summary of the new blog account's details are emailed to the author.



Table 2-5. The Create a new Personal Wiki use case description also gets a makeover

Use case name

Create a new Personal Wiki

Related Requirements

Requirement A.2

Goal In Context

A new or existing author requests a new personal Wiki from the Administrator.

Preconditions

The author has appropriate proof of identity.

Successful End Condition

A new personal Wiki is created for the author.

Failed End Condition

The application for a new personal Wiki is rejected.

Primary Actors

Administrator

Secondary Actors

None

Trigger

The Administrator asks the CMS to create a new personal Wiki.

Included Cases

Check Identity

Main Flow

Step

Action

 

1

The Administrator asks the system to create a new personal Wiki.

 

2

The Administrator enters the author's details.

 

3

include::Check Identity

The author's details are checked.

 

5

The new personal Wiki is created.

 

6

A summary of the new personal Wiki's details are emailed to the author.



Now you can create a use case description for the reusable steps within the Check Identity use case, as shown in Table 2-6.


Table 2-6. The Check Identity use case description contains the reusable steps

Use case name

Check Identity

Related Requirements

Requirement A.1, Requirement A.2.

Goal In Context

An author's details need to be checked and verified as accurate.

Preconditions

The author being checked has appropriate proof of identity.

Successful End Condition

The details are verified.

Failed End Condition

The details are not verified.

Primary Actors

Author Credentials Database.

Secondary Actors

None.

Trigger

An author's credentials are provided to the system for verification.

Main Flow

Step

Action

 

1

The details are provided to the system.

 

2

The Author Credentials Database verifies the details.

 

3

The details are returned as verified by the Author Credentials Database.

Extensions

Step

Branching Action

 

2.1

The Author Credentials Database does not verify the details.

 

2.2

The details are returned as unverified.



Why bother with all this hassle with reuse between use cases? Why not just have two use cases and maintain the similar steps separately? All this reuse has two important benefits:


  • Reuse using <<include>> removes the need for tedious cut-and-paste operations between use case descriptions, since updates are made in only one place instead of every use case.

  • The <<include>> relationship gives you a good indication at system design time that the implementation of Check Identity will need to be a reusable part of your system.




2.2.2. Special Cases







Sometimes you'll come across a use case whose behavior, when you start to analyze it more carefully, can be applied to several different cases, but with small changes. Unlike the <<include>> relationship, which allows you to reuse a small subset of behavior, this is applying a use case with small changes for a collection of specific situations. In object-oriented terms, you potentially have a number of specialized cases of a generalized use case.


Let's take a look at an example. Currently, the Content Management System contains a single Create a new Blog Account use case that describes the steps required to create an account. But what if the CMS supports several different types of blog accounts, and the steps required to create each of these accounts differs ever so slightly from the original use case? You want to describe the general behavior for creating a blog accountcaptured in the Create a new Blog Account use caseand then define specialized use cases in which the account being created is a specific type, such as a regular account with one blog or an editorial account that can make changes to entries in a set of blogs.


This is where use case generalization comes in. A more common way of referring to generalization is using the term inheritance
. Use case inheritance is useful when you want to show that one use case is a special type of another use case. To show use case inheritance
, use the generalization arrow to connect the more general, or parent, use case to the more specific use case. Figure 2-13 shows how you could extend the CMS's use cases to show that two different types of blog accounts can be created.



Figure 2-13. Two types of blog account, regular and editorial, can be created by the Management System



Taking a closer look at the Create a new Editorial Blog Account specialized use case description, you can see how most of the behavior from the more general Create a new Blog Account use case is reused. Only the details that are specific to creating a new editorial account need to be added (see Table 2-7).


Table 2-7. You can show that a use case is a special case of a more general use case within the detailed description using the Base Use Cases field

Use case name

Create a new Editorial Blog Account

Related Requirements

Requirement A.1.

Goal In Context

A new or existing author requests a new editorial blog account from the Administrator .

Preconditions

The author has appropriate proof of identity.

Successful End Condition

A new editorial blog account is created for the author.

Failed End Condition

The application for a new editorial blog account is rejected.

Primary Actors

Administrator.

Secondary Actors

None.

Trigger

The Administrator asks the CMS to create a new editorial account that will allow an author to edit entries in a set of blogs.

Base Use Cases

Create a new Blog Account

Main Flow

Step

Action

 

1

The Administrator asks the system to create a new blog account.

 

2

The Administrator selects the editorial account type.

 

3

The Administrator enters the author's details.

 

4

The Administrator selects the blogs that the account is to have editorial rights over.

 

5

include::Check Identity

The author's details are checked.

 

6

The new editorial account is created.

 

7

A summary of the new editorial account's details are emailed to the author.

Extensions

Step

Branching Action

 

5.1

The author is not allowed to edit the indicated blogs.

 

5.2

The editorial blog account application is rejected.

 

5.3

The application rejection is recorded as part of the author's history.



Use case inheritance is a powerful way of reusing a use case so that you only have to specify the extra steps that are needed in the more specific use cases. See Chapter 5 for more information on inheritance between classes.


But be carefulby using inheritance, you are effectively saying that every step in the general use case must occur in the specialized use cases. Also, every relationship that the general use case has with external actors or use cases, as shown with the <<include>> relationship between Create a new Blog Account and Check Identity, must also make sense in the more specialized use cases, such as Create a new Editorial Blog Account.


If you really don't want your more specific use case to do everything that the general use case describes, then don't use generalization. Instead, you might want to consider using either the <<include>> relationship shown in the previous section or the <<extend>> relationship coming up in the next section.




2.2.3. The <<extend>> Relationship






Any explanation of the <<extend>> stereotype should be preceded by a warning that it is the most heavily debated type of use case relationship. Almost nothing is less understood or harder to accurately communicate within the UML modeling community than the <<extend>> use case relationship, and this presents a bit of a problem when you are trying to learn about it. Figure 2-14 shows you how <<extend>> works; take a look, and then let's dive into some UML concept and theory.



Figure 2-14. The <<extend>> use case relationship looks a bit like the <<include>> relationship, but that's where the similarities end



At first glanceparticularly if you are a Java programmer<<extend>> seems very similar to inheritance between classes. In Java, a class can extend from a base class. Similarly, in C++ and C#, you can declare inheritance between classes, and you would often say that a class extends another class. In both these cases, the extend relationship between classes means inheritance. So, for a programmer, it follows that <<extend>> should mean something like inheritance, right?


Alarm bells should definitely be going off now. You already saw in the previous section how use cases declare inheritance using a generalization arrow, so why would you need yet another type of arrow with an <<extend>> stereotype? Does the generalization arrow mean the same thing as the <<extend>> stereotype? Unfortunately, the <<extend>> stereotype has very little in common with inheritance, and so the two definitely do not mean the same thing.


The designers of UML 2.0 took a very different view as to the meaning of <<extend>> between use cases. They wanted a means for you to show that a use case might completely reuse another use case's behavior, similar to the <<include>> relationship, but that this reuse was optional and dependent either on a runtime or system implementation decision.


From the CMS example, the Create a new Blog Account use case might want to record that a new author applied for an account and was rejected, adding this information to the author's application history. Extra steps can be added to the Create a new Blog Account use case's description to show this optional behavior, as shown in Step 4.3 in Table 2-8.


Table 2-8. Behavior that is a candidate for <<extend>> relationship reuse can usually be found in the Extensions section of a use case description

Use case name

Create a new Blog Account

Related Requirements

Requirement A.1.

Goal In Context

A new or existing author requests a new blog account from the Administrator.

Preconditions

The author has appropriate proof of identity.

Successful End Condition

A new blog account is created for the author.

Failed End Condition

The application for a new blog account is rejected.

Primary Actors

Administrator.

Secondary Actors

None.

Trigger

The Administrator asks the CMS to create a new blog account.

Included Cases

Check Identity

Main Flow

Step

Action

 

1

The Administrator asks the system to create a new blog account.

 

2

The Administrator selects an account type.

 

3

The Administrator enters the author's details.

 

4

include::Check Identity

The author's details are checked.

 

5

The new account is created.

 

6

A summary of the new blog account's details are emailed to the author.

Extensions

Step

Branching Action

 

4.1

The author is not allowed to create a new blog.

 

4.2

The blog account application is rejected.

 

4.3

The application rejection is recorded as part of the author's history.



The same behavior captured in Step 4.3 would also be useful if the customer was refused an account for some reason during the Create a new Personal Wiki use case's execution. According to the requirements, this reusable behavior is optional in both cases; you don't want to record a rejection if the application for a blog account or a personal Wiki was accepted. The <<extend>> relationship is ideal in this sort of reuse situation, as shown in Figure 2-15.



Figure 2-15. The <<extend>> relationship comes into play to show that both the "Create a new Personal Wiki" and "Create a new Blog Account" use cases might occasionally share the application rejection recording behavior



The new Record Application Failure use case, as the name implies, captures all of the behavior associated with recording an author's application failure whether it be for a personal Wiki or for a specific type of blog account. Using the <<extend>> relationship, the Record Application Failure use case's behavior is optionally reused by the Create a new Blog Account and Create a new Personal Wiki use cases if an application is rejected.













How to Make Dialogs











 < Day Day Up > 





How to Make Dialogs



Several classes support dialogs�windows that are more limited than frames. To create simple, standard dialogs, you use the JOptionPane class.[31] The ProgressMonitor class can put up a dialog that shows the progress of an operation.[32] Two other classes, JColorChooser and JFileChooser, also supply standard dialogs.[33] To bring up a print dialog, you use the Printing API.[34] To create custom dialogs, use the JDialog[35] class directly.

[31] JOptionPane API documentation: http://java.sun.com/j2se/1.4.2/docs/api/javax/swing/JOptionPane.html.

[32] See How to Use Progress Bars (page 300).

[33] See How to Use Color Choosers (page 167) and How to Use File Choosers (page 206).

[34] You can learn more about printing in the "2D" trail in The Java Tutorial on this book's CD and online at: http://java.sun.com/docs/books/tutorial/2d.

[35] JDialog API documentation: http://java.sun.com/j2se/1.4.2/docs/api/javax/swing/JDialog.html.



The code for simple dialogs can be minimal. Figure 11, for example, shows an informational dialog.



Figure 11. A simple dialog.




Here's the code that creates and shows the dialog:





JOptionPane.showMessageDialog(frame,

"Eggs aren't supposed to be green.");



An Overview of Dialogs



Every dialog is dependent on a frame. When the frame is destroyed, so are its dialogs. When the frame is iconified, its dialogs disappear from the screen. When the frame is deiconified, its dialogs return to the screen. The AWT automatically provides this behavior.



A dialog can be modal. When a modal dialog is visible, it blocks user input to all other windows in the program. The dialogs that JOptionPane provides are modal. To create a nonmodal dialog, you must use the JDialog class directly.



The JDialog class is a subclass of the AWT java.awt.Dialog class. It adds to Dialog a root pane and support for a default close operation. These are the same features that JFrame has, and using JDialog directly is very similar to using JFrame directly. If you're going to use JDialog directly, then you should understand the material in Using Top-Level Containers (page 46) in Chapter 3 and How to Make Frames (Main Windows) (page 236) later in this chapter, especially Responding to Window-Closing Events (page 240).



Even when you use JOptionPane to implement a dialog, you're still using a JDialog behind the scenes. The reason is that JOptionPane is simply a container that can automatically create a JDialog and add itself to the JDialog's content pane.



The DialogDemo Example



Figure 12 is a picture of an application that displays dialogs.



Figure 12. The DialogDemo application.




Try This:













  1. Run DialogDemo using Java Web Start or compile and run the source code yourself.[36]

    [36] To run DialogDemo using Java Web Start, click the DialogDemo link on the RunExamples/components.html page on the CD. You can find the source files here: JavaTutorial/uiswing/components/example-1dot4/index.html#DialogDemo.

  2. Click the Show it! button. A modal dialog will appear. Until you close it, the application will be unresponsive, although it will repaint itself if necessary. You can close the dialog by clicking a button in the dialog or you can close it explicitly, such as by using the dialog's window decorations.

  3. Iconify the DialogDemo window while a dialog is showing. The dialog will disappear from the screen until you deiconify the DialogDemo window.

  4. In the More Dialogs pane, click the bottom radio button and then the Show it! button. A nonmodal dialog will appear. Note that the DialogDemo window remains fully functional while the nonmodal dialog is up.



JOptionPane Features



Using JOptionPane, you can create and customize several different kinds of dialogs. JOptionPane provides support for laying out standard dialogs, providing icons, specifying the dialog's title and text, and customizing the button text. Other features allow you to customize the components the dialog displays and specify where the dialog should appear onscreen. You can even specify that an option pane put itself into an internal frame (JInternalFrame) instead of a JDialog.





Note:

The internal frames that JOptionPane creates currently behave differently from modal dialogs. They don't behave modally and in general seem more like frames than like dialogs. For this reason, we don't currently recommend their use.




When you create a JOptionPane, look-and-feel-specific code adds components to it and determines their layout.



JOptionPane's icon support lets you easily specify which icon the dialog displays. You can use a custom icon, no icon at all, or any one of four standard JOptionPane icons (question, information, warning, and error). Each look and feel has its own versions of the four standard icons. Figure 13 shows the icons used in the Java look and feel.



Figure 13. Icons provided by JOptionPane (Java look and feel shown).




Creating and Showing Simple Dialogs



Most simple modal dialogs you create and show using one of JOptionPane's showXxx- Dialog methods. If your dialog should be an internal frame, add Internal after show�for example, showMessageDialog changes to showInternalMessageDialog. If you need to control the dialog's window-closing behavior or if the dialog isn't modal, you should directly instantiate JOptionPane and add it to a JDialog instance. Then invoke setVisible(true) on the JDialog to make it appear.



The two most useful showXxxDialog methods are showMessageDialog and showOption-Dialog. The showMessageDialog method displays a simple, one-button dialog. The show-OptionDialog method displays a customized dialog that can display a variety of buttons with customized button text and can contain a standard text message or a collection of components.



The other two showXxxDialog methods are used less often. The showConfirmDialog method asks the user to confirm something, but has the disadvantage of having standard button text (Yes/No or the localized equivalent, for example) rather than button text customized to the user's situation (Start/Cancel, for example). A fourth method, showInputDialog, is designed to display a modal dialog that gets a string from the user, using either a text field or an uneditable combo box.



The following are some examples, taken from DialogDemo.java, of using showMessageDialog, showOptionDialog, and the JOptionPane constructor. For more example code, see DialogDemo.java and the other programs listed in Examples That Use Dialogs (page 199) later in this chapter.



showMessageDialog


Displays a modal dialog with one button, which is labeled OK (or the localized equivalent). You can easily specify the message, icon, and title the dialog displays. Table 12 shows some examples.



Table 12. Examples Using showMessageDialog





//default title and icon

JOptionPane.showMessageDialog(frame,

"Eggs aren't supposed to be green.");





//custom title, warning icon

JOptionPane.showMessageDialog(frame,

"Eggs aren't supposed to be green.",

"Inane warning",

JOptionPane.WARNING_MESSAGE);





//custom title, error icon

JOptionPane.showMessageDialog(frame,

"Eggs aren't supposed to be green.",

"Inane error",

JOptionPane.ERROR_MESSAGE);





//custom title, no icon

JOptionPane.showMessageDialog(frame,

"Eggs aren't supposed to be green.",

"A plain message",

JOptionPane.PLAIN_MESSAGE);





//custom title, custom icon

JOptionPane.showMessageDialog(frame,

"Eggs aren't supposed to be green.",

"Inane custom dialog",

JOptionPane.INFORMATION_MESSAGE,

icon);



showOptionDialog


Displays a modal dialog with the specified buttons, icons, message, title, and so on. With this method, you can change the text that appears on the buttons of standard dialogs and perform many other kinds of customization. (See Table 13.)



Table 13. An Example Using showOptionDialog





//Custom button text

Object[] options = {"Yes, please",

"No, thanks",

"No eggs, no ham!"};

int n = JOptionPane.showOptionDialog(frame,

"Would you like some green eggs to go "

+ "with that ham?",

"A Silly Question",

JOptionPane.YES_NO_CANCEL_OPTION,

JOptionPane.QUESTION_MESSAGE,

null,

options,

options[2]);



JOptionPane (constructor)


Creates a JOptionPane with the specified buttons, icons, message, title, and so on. You then have to add the option pane to a JDialog, register a property-change listener on the option pane, and show the dialog. (See Table 14.) See Stopping Automatic Dialog Closing (page 195) for details.



Table 14. An Example Using JOptionPane





final JOptionPane optionPane = new JOptionPane(

"The only way to close this dialog is by\n"

+ "pressing one of the following buttons.\n"

+ "Do you understand?",

JOptionPane.QUESTION_MESSAGE,

JOptionPane.YES_NO_OPTION);



The arguments to all of the showXxxDialog methods and JOptionPane constructors are standardized, though the number of arguments for each method and constructor varies. The following list describes each argument. To look at the complete list of arguments for a particular method, see The Dialog API (page 196).



Component parentComponent


Always the first argument to each showXxxDialog method, it must be a frame, a component inside a frame, or null. If you specify a frame, the dialog will appear over its center and depend on it. If you specify a component inside a frame, the dialog will appear over the center of that component and depend on that component's frame. If you specify null, the look and feel picks an appropriate position for the dialog�generally the center of the screen�and the dialog doesn't depend on any visible frame.



The JOptionPane constructors don't include this argument. Instead, you specify the parent frame when you create the JDialog that contains the JOptionPane and use the JDialog setLocationRelativeTo method to set the dialog's position.



Object message


A required argument, this specifies what the dialog should display in its main area. Generally, you specify a string, which results in the dialog displaying a label with the specified text. You can split the message over several lines by putting newline (\n) characters inside the message string. For example:





"Complete the sentence:\n \"Green eggs and...\""



String title


Specifies the title of the dialog.



int optionType


Specifies the buttons that appear at the bottom of the dialog. Choose from one of the following standard sets:



DEFAULT_OPTION, YES_NO_OPTION, YES_NO_CANCEL_OPTION, OK_CANCEL_OPTION.



int messageType


Determines the icon displayed in the dialog. Choose from the following values:



PLAIN_MESSAGE (no icon), ERROR_MESSAGE, INFORMATION_MESSAGE, WARNING_MESSAGE, QUESTION_MESSAGE.



Icon icon


The icon to display in the dialog.



Object[] options


Further specifies the option buttons to appear at the bottom of the dialog. Generally, you specify an array of strings for the buttons. See Customizing Button Text (page 194) for more information.



Object initialValue


Specifies the default value to be selected. You can either let the default icon be used or specify the icon using the message type or icon argument. By default, a dialog created with showMessageDialog displays the information icon, and a dialog created with showConfirmDialog or showInputDialog displays the question icon. An option pane created with a JOptionPane constructor displays no icon by default. To specify that the dialog display a standard icon or no icon, specify the message type. To specify a custom icon, use the icon argument. The icon argument takes precedence over the message type; as long as the icon argument has a non-null value, the dialog displays the specified icon.



Customizing Button Text



When you use JOptionPane to create a dialog, you can choose either to use the standard button text (which might vary by look and feel) or to specify different text.



The code shown in Table 15, taken from DialogDemo.java, creates two Yes/No dialogs. The first is implemented with showConfirmDialog, which uses the look-and-feel wording for the two buttons. The second uses showOptionDialog so that it can customize the wording. With the exception of wording changes, the dialogs are identical.



Table 15. Two Yes/No Dialog Examples





//default icon, custom title

int n = JOptionPane.showConfirmDialog(

frame,

"Would you like green eggs and ham?",

"An Inane Question",

JOptionPane.YES_NO_OPTION);





Object[] options = {"Yes, please",

"No way!"};

int n = JOptionPane.showOptionDialog(frame,

"Would you like green eggs and ham?",

"An Inane Question",

JOptionPane.YES_NO_OPTION,

JOptionPane.QUESTION_MESSAGE,

null, //don't use a custom Icon

options, //the titles of buttons

options[0]); //default button title



Getting the User's Input from a Dialog



As the previous code snippets in Table 15 show, the showMessageDialog, showConfirm-Dialog, and showOptionDialog methods return an integer indicating the user's choice. The values for this integer are YES_OPTION, NO_OPTION, CANCEL_OPTION, OK_OPTION, and CLOSED_OPTION. Except for CLOSED_OPTION, each option corresponds to the button the user presses. CLOSED_OPTION indicates that the user is closing the dialog window explicitly rather than by choosing a button inside the option pane.



Even if you change the strings that the standard dialog buttons display, the return value is still one of the predefined integers. For example, a YES_NO_OPTION dialog always returns one of the following values: YES_OPTION, NO_OPTION, or CLOSED_OPTION.



If you're designing a custom dialog, on the other hand, you need to design its API so that you can query the dialog about what the user chose. For example, the dialog implemented in CustomDialog.java[37] has a getValidatedText method that returns the text the user entered.

[37] You can find CustomDialog.java here: JavaTutorial/uiswing/components/example-1dot4/CustomDialog.java.



Stopping Automatic Dialog Closing



By default, when the user clicks a JOptionPane-created button, the dialog closes. But what if you want to check the user's answer before closing the dialog? In this case, you must implement your own property-change listener so that when the user clicks a button the dialog doesn't automatically close.



DialogDemo contains two dialogs that implement a property-change listener. One of these is a custom modal dialog, implemented in CustomDialog, that uses JOptionPane both to get the standard icon and to get layout assistance. The other dialog, whose code is below, uses a standard Yes/No JOptionPane. Though this dialog is useless as written, its code is simple enough that you can use it as a template for more complex dialogs.



Besides setting the property-change listener, the following code also calls JDialog's set-DefaultCloseOperation method and implements a window listener that handles the window close attempt properly. If you don't care to be notified when the user closes the window explicitly, ignore the bold code.





final JOptionPane optionPane = new JOptionPane(

"The only way to close this dialog is by\n"

+ "pressing one of the following buttons.\n"

+ "Do you understand?",

JOptionPane.QUESTION_MESSAGE,

JOptionPane.YES_NO_OPTION);



final JDialog dialog = new JDialog(frame, "Click a button", true);

dialog.setContentPane(optionPane);

dialog.setDefaultCloseOperation(

JDialog.DO_NOTHING_ON_CLOSE);

dialog.addWindowListener(new WindowAdapter() {

public void windowClosing(WindowEvent we) {

setLabel("Thwarted user attempt to close window.");

}

});



optionPane.addPropertyChangeListener(

new PropertyChangeListener() {

public void propertyChange(PropertyChangeEvent e) {

String prop = e.getPropertyName();



if (dialog.isVisible()

&& (e.getSource() == optionPane)

&& (prop.equals(JOptionPane.VALUE_PROPERTY) ||

prop.equals(JOptionPane.INPUT_VALUE_PROPERTY)))

{

//If you were going to check something

//before closing the window, you'd do

//it here.

dialog.setVisible(false);

}

}

});

dialog.pack();

dialog.setVisible(true);



int value = ((Integer)optionPane.getValue()).intValue();

if (value == JOptionPane.YES_OPTION) {

setLabel("Good.");

} else if (value == JOptionPane.NO_OPTION) {

setLabel("Try using the window decorations "

+ "to close the non-auto-closing dialog. "

+ "You can't!");

}



The Dialog API



Tables 16 through 18 list the commonly used JOptionPane[38] and JDialog[39] constructors and methods. Other methods you're likely to call are defined by the Dialog, Window, and Component classes and include pack, setSize, and setVisible.

[38] JOptionPane API documentation: http://java.sun.com/j2se/1.4.2/docs/api/javax/swing/JOptionPane.html.

[39] JDialog API documentation: http://java.sun.com/j2se/1.4.2/docs/api/javax/swing/JDialog.html.



Table 16. Showing Standard Modal Dialogs (Using JOptionPane Class Methods)

Method

Purpose





static void showMessageDialog(Component,

Object)

static void showMessageDialog(Component,

Object,

String, int)

static void showMessageDialog(Component,

Object,

String,

int, Icon)

Show a one-button, modal dialog that gives the user some information. The arguments specify (in order) parent component, message, title, message type, and icon for the dialog. See Creating and Showing Simple Dialogs (page 190) for a discussion of the arguments and their effects.





static int showOptionDialog(Component, Object,

String, int, int,

Icon, Object[],

Object)

Show a customized modal dialog. The arguments specify (in order) parent component, message, title, option type, message type, icon, options, and initial value for the dialog. See also Creating and Showing Simple Dialogs (page 190).





static int showConfirmDialog(Component, Object)

static int showConfirmDialog(Component, Object,

String, int)

static int showConfirmDialog(Component, Object,

String, int, int)

static int showConfirmDialog(Component, Object,

String,

int, int, Icon)

Show a modal dialog that asks the user a question. The arguments specify (in order) parent component, message, title, option type, message type, and icon for the dialog. See also Creating and Showing Simple Dialogs (page 190).





static String showInputDialog(Object)

static String showInputDialog(Component,

Object)

static String showInputDialog(Component,

Object,

String, int)

static String showInputDialog(Component,

Object,

String,

int,

Icon,

Object[],

Object)

Show a modal dialog that prompts the user for input. The single-argument version specifies just the message, with the parent component assumed to be null. The arguments for the other versions specify (in order) parent component, message, title, message type, icon, options, and initial value for the dialog. See also Creating and Showing Simple Dialogs (page 190).





static void showInternalMessageDialog(...)

static void showInternalOptionDialog(...)

static void showInternalConfirmDialog(...)

static String showInternalInputDialog(...)

Implement a standard dialog as an internal frame. See Table 17 (page 198) for the exact list of arguments.



Table 17. Methods for Using JOptionPanes Directly

Method or Constructor

Purpose





JOptionPane()

JOptionPane(Object)

JOptionPane(Object, int)

JOptionPane(Object, int, int)

JOptionPane(Object, int, int, Icon)

JOptionPane(Object, int, int, Icon, Object[])

JOptionPane(Object, int, int, Icon,

Object[], Object)

Creates a JOptionPane instance. See Creating and Showing Simple Dialogs (page 190) for a discussion of the arguments and their effects.





static Frame getFrameForComponent(Component)

static JDesktopPane

getDesktopPaneForComponent(Component)

Handy JOptionPane class methods that find the frame or desktop pane, respectively, that the specified component is in.



Table 18. Frequently Used JDialog Constructors and Methods

Method or Constructor

Purpose





JDialog()

JDialog(Dialog)

JDialog(Dialog, boolean)

JDialog(Dialog, String)

JDialog(Dialog, String, boolean)

JDialog(Dialog, String, boolean,

GraphicsConfiguration)

JDialog(Frame)

JDialog(Frame, boolean)

JDialog(Frame, String)

JDialog(Frame, String, boolean)

JDialog(Frame, String, boolean,

GraphicsConfiguration)

Create a JDialog instance. The Frame argument, if any, is the frame (usually a JFrame object) that the dialog depends on. Make the boolean argument true to specify a modal dialog, false or absent to specify a nonmodal dialog. You can also specify the title of the dialog using a string argument. The constructors taking the java.awt.GraphicsConfiguration argument were introduced in 1.4.





void setContentPane(Container)

Container getContentPane()

Get and set the content pane, which is usually the container of all the dialog's components. See Using Top-Level Containers (page 46) for more information.





void setDefaultCloseOperation(int)

int getDefaultCloseOperation()

Get and set what happens when the user tries to close the dialog. Possible values: DISPOSE_ON_CLOSE, DO_NOTHING_ON_CLOSE, HIDE_ON_CLOSE (the default). See Responding to Window-Closing Events (page 240) for more information.

void setLocationRelativeTo(Component)

Center the dialog over the specified component.





static void

setDefaultLookAndFeelDecorated(boolean)



static boolean

isDefaultLookAndFeelDecorated()

Set or get a hint as to whether the dialog's window decorations (such as borders or widgets to close the window) should be provided by the current look and feel. Otherwise the dialog's decorations are provided by the current window manager. Note that this is only a hint, as some look and feels do not support this feature. Introduced in 1.4.



Examples That Use Dialogs



The following table lists examples that use JOptionPane or JDialog. To find other examples that use dialogs, see these sections: Examples That Monitor Progress (page 310), Examples That Use Color Choosers (page 175), and Examples That Use File Choosers (page 220).



Example

Where Described

Notes

DialogDemo, CustomDialog

This section

Creates many kinds of dialogs using JOptionPane and JDialog.

Framework

�

Brings up a confirmation dialog when the user selects the Quit menu item.

ListDialog

How to Use BoxLayout (page 462)

Implements a modal dialog containing a scrolling list and two buttons. Doesn't use JOptionPane, except for the utility method getFrameForComponent.

TableDialogEditDemo

How to Use Tables (page 388)

Implements a table with a dialog that indirectly serves as a cell editor.













     < Day Day Up > 



    Calling Multiple Controllers and Views



    [ Team LiB ]





    Calling Multiple Controllers and Views


    One of the things you will notice in the controller servlet is that it has direct knowledge of the JSP that is handling the view�the name of the view that the JSP is coded in. You should strive to break such dependencies whenever you can. What happens if you want to do things exactly the same way in the controller but display a different view of the data?


    The controller should be concerned with sending information to the model, and the view should be concerned with displaying the output. The only thing that ties the controller to the view at the moment is the fact that the controller contains the logic to forward the request on to the view. The way to completely separate the controller from the view is with a dispatcher servlet.


    A dispatcher performs the crucial transition between the controller and the view. Instead of invoking a controller directly, you call the dispatcher and tell it which controller you want to call and which view to display. That way, the controller doesn't have any specific view hardwired into its code. Likewise, the dispatcher doesn't have a view hardwired in, either.


    Don't Confuse This Dispatcher with RequestDispatcher

    This is not the same dispatcher as the RequestDispatcher class that is part of the Servlet API. This section of the book refers to a dispatcher in the generic sense.



    You can even have the dispatcher call multiple controllers before invoking a view. That way, you can break your business logic down into finer-grained pieces. When the client sends a request to the server, it may invoke several controllers to update various portions of the model before displaying the view.


    Listing 20.4 shows the dispatcher servlet. In this example, you use parameters (form variables) named controller to pass the controllers. The pathname for the default view is passed in the view parameter, whereas the pathname for the error-handler view is passed in the errorView parameter.


    Listing 20.4 Source Code for DispatcherServlet.java



    package examples;

    import javax.servlet.*;

    public class DispatcherServlet extends GenericServlet
    {
    public void service(ServletRequest request,
    ServletResponse response)
    throws java.io.IOException, ServletException
    {

    // Get the list of controllers to call.
    String[] controllers =
    request.getParameterValues("controller");

    // Get the name of the view to call.
    String viewName = request.getParameter("view");

    // Get the name of the view to call if there is an error.
    String errorViewName = request.getParameter("errorView");

    try
    {
    for (int i=0; i < controllers.length; i++)
    {
    RequestDispatcher d =
    getServletContext().
    getRequestDispatcher(
    controllers[i]);
    if (d != null)
    {
    // Invoke the next controller.
    d.include(request, response);
    }
    else
    {
    getServletContext().log(
    "No controller named " +
    controllers[i]);
    }
    }

    RequestDispatcher d = getServletContext().
    getRequestDispatcher(viewName);

    // The dispatcher includes the other controllers, but it forwards to the view.
    if (d != null)
    {
    d.forward(request, response);
    }
    else
    {
    getServletContext().log(
    "No view named "+ viewName);
    }
    }
    catch (Exception exc)
    {
    // If there is an error, forward to the error view.

    request.setAttribute("exception", exc.toString());

    RequestDispatcher d = getServletContext().
    getRequestDispatcher(errorViewName);

    if (d != null)
    {
    d.forward(request, response);
    }
    else
    {
    getServletContext().log(
    "No errorView named " + errorViewName);
    }
    }
    }
    }

    To use this dispatcher with the ControllerServlet, you need to strip a few things out of the controller. You no longer need to include the calls to gotoPage because the dispatcher is handling that. Also, rather than have it call the error page, make the controller throw a ServletException with the reason for the error. Listing 20.5 gives the source for the modified ControllerServlet.


    Listing 20.5 Source Code for ControllerServlet2.java



    package examples;

    import java.io.*;
    import java.util.*;
    import javax.servlet.*;

    public class ControllerServlet2 extends GenericServlet
    {
    private static Person[] people = new Person[]
    {
    new Person("Samantha Tippin", 9, "770-123-4567"),
    new Person("Kaitlyn Tippin", 6, "770-123-4567"),
    new Person("Edward Alexander", 3, "No phone"),
    new Person("Star Alexander", 3, "Phone off hook"),
    new Person("Norton Alexander", 12, "No phone")
    };


    public synchronized void service(ServletRequest request,
    ServletResponse response)
    throws java.io.IOException, ServletException
    {
    String minimumAgeStr = request.getParameter("minAge");
    int minimumAge = 0;

    try
    {
    minimumAge = Integer.parseInt(minimumAgeStr);
    }
    catch (Exception exc)
    {
    throw new ServletException("Invalid minimum age");
    }

    String maximumAgeStr = request.getParameter("maxAge");
    int maximumAge = 0;

    try
    {
    maximumAge = Integer.parseInt(maximumAgeStr);
    }
    catch (Exception exc)
    {
    throw new ServletException("Invalid maximum age");
    }

    // Get all the people matching the criteria
    Vector v = new Vector();

    for (int i=0; i < people.length; i++) {
    if ((people[i].age >= minimumAge) &&
    (people[i].age <= maximumAge)) {
    v.addElement(people[i]);
    }
    }

    // Store the vector of person objects so the JSP can access it
    request.setAttribute("people", v);
    }
    }

    You don't need to change anything in the ShowPeople.jsp page to make it work with the dispatcher. The only other thing you need to do is modify the initial HTML form. It now needs to pass parameters to the dispatcher to tell it which controller and view to use. You can insert the information as hidden form variables so that it is automatically passed when the user submits the form. Listing 20.6 shows the modified HTML form.


    Listing 20.6 Source Code for PeopleQuery2.html



    <html>
    <body>

    Please enter the minimum and maximum ages to view:
    <P>
    <form action="/DispatcherServlet" method="post">

    <input type=hidden name="controller"
    value="/ControllerServlet2">
    <input type=hidden name="view" value="/ShowPeople.jsp">
    <input type=hidden name="errorView"
    value="/ErrorHandler.jsp">

    Minimum Age: <input type="text" name="minAge"><br>
    Maximum Age: <input type="text" name="maxAge"><br>
    <P>
    <input type="submit" value="Perform Query!">
    </form>
    </body>
    </html>




      [ Team LiB ]



      Overview




















      Chapter 6 - Thread Prioritization

      Java Thread Programming
      Paul
      Hyde






      size=1>  size=2>Copyright � 1999 Sams
      Publishing




















      size=5>Chapter 6: size=5>Thread Prioritization












      size=4>Overview












      size=2>Java allows you to give each of the threads running in a
      virtual machine a
      size=2>priority.
      Higher-priority threads generally get more of a chance to run than
      lower-priority threads, but exact thread-scheduling behavior varies
      by VM implementation and operating system. Thread prioritization can
      be used to provide suggestions to the VM as to how you would like
      the threads to take turns running on the processor relative to each
      other, increasing an application’s responsiveness to relatively more
      important events.












      valign="top" bgcolor="#FFFFFF">

      Toc



      Section 9.6. A Participant's State-Line










      9.6. A Participant's State-Line






      Now that you have added time to the timing diagram (fancy that!), you can show what state a participant is in at any given time. If you take a look back at Figure 9-6 and Figure 9-7, you can already see how participant's current state is indicated: with a horizontal line that is called the state-line.


      At any given time in the interaction, a participant's state-line is aligned with one of the participant's states (see Figure 9-9).



      Figure 9-9. In this example, p1:Participant's state-line indicates that it is in State1 for 1 unit of time, State2 for three units of time, and State3 for roughly five units of time (before returning to State1 at the end of the interaction)



      Figure 9-10 shows how the Create a new Regular Blog Account timing diagram is updated to show the state of each participant at a given time during the interaction.


      In practice, you would probably add both events and states to a timing diagram at the same time. We've split the two activities here simply because it makes it easier for you to see how the two pieces of notation are applied (without confusing one with the other).



      That's all there is to showing that a participant is in a specific state at a given time. Now it's time to look at why a participant changes states in the first place, which leads us neatly to events and messages.



      Figure 9-10. Each of the participants needs to have a corresponding state-line to indicate their state at any given point in time













      Workshop



      [ Team LiB ]





      Workshop


      The Workshop is designed to help you review what you have learned and help you further increase your understanding of the material covered in this hour.


      Quiz


      1:

      What are some of the effects of including a resource at compile time or run time?

      2:

      What is jspf?

      3:

      What class is used by servlets to include or forward to a resource?

      4:

      If you want the client of a page to see the output of a resource that forwards to another, what can you do?



      Answers

      A1:

      Resources that are included at compile time produce a compound resource that is used at runtime. The one becomes a part of the other. There may be a performance advantage since the runtime component is "prepared beforehand." Resources that are included at compile time cause the result of their evaluation at runtime to become a part of the output of the other. The most important effect of this is that the resources included at runtime are more limited�for example, they cannot set headers. However, this combination is often more flexible, since the included file can also be determine at runtime. Beyond simply selecting the resource at runtime, you can also mix servlets and JSPs.

      A2:

      jspf is an extension used with jsp segments, which are syntactically the same as a JSP, but are designed for inclusion as a type of component.

      A3:

      A RequestDispatcher is used for both operations. You use its include and forward methods.

      A4:

      Recall that forwarding to another resource causes the output buffer to be cleared. In most cases, this is desireable. If you want the client to see the output of the first page, flush the buffer prior to forwarding.



      Activities


      1. Write a JSP that includes another JSP at runtime. Pass a dynamic parameter such as the current time between the two. Display the parameter in the included page. Do this once using scriptlets or declarations and the other time without.

      2. Repeat the previous exercise, substituting a servlet for the first JSP.





        [ Team LiB ]