AddressBookExample/ 0000700 0000770 0000120 00000000000 10661133363 014772 5 ustar bjork admin 0000000 0000000 AddressBookExample/Code/ 0000700 0000770 0000120 00000000000 10227025157 015643 5 ustar bjork admin 0000000 0000000 AddressBookExample/Code/AddressBookApplication.java 0000700 0000770 0000120 00000004521 10234507775 023110 0 ustar bjork admin 0000000 0000000 /* * AddressBookApplication.java * * Main program for address book application * * Copyright (c) 2001, 2003, 2005 - Russell C. Bjork * */ import java.awt.Frame; import java.awt.event.WindowEvent; // The next line is only needed on the Mac platform - comment out // if compiling on some other platform (but comment back in and recompile // before moving final version to server) import com.apple.eawt.*; /** Main class for the Address Book example */ public class AddressBookApplication { /** Main method for program */ public static void main(String [] args) { FileSystem fileSystem = new FileSystem(); AddressBookController controller = new AddressBookController(fileSystem); AddressBookGUI gui = new AddressBookGUI(controller, new AddressBook()); gui.show(); // Register a Mac quit handler - comment out if compiling on some // other platform (but comment back in and recompile // before moving final version to server) com.apple.eawt.Application application = com.apple.eawt.Application.getApplication(); application.addApplicationListener(new ApplicationAdapter() { public void handleQuit(ApplicationEvent e) { e.setHandled(false); quitApplication(); } }); } /** Terminate the application (unless cancelled by the user) */ public static void quitApplication() { // When the user requests to quit the application, any open // windows must be closed Frame [] openWindows = Frame.getFrames(); for (int i = 0; i < openWindows.length; i ++) { // Attempt to close any window that belongs to this program if (openWindows[i] instanceof AddressBookGUI) { openWindows[i].dispatchEvent(new WindowEvent( openWindows[i], WindowEvent.WINDOW_CLOSING)); // If the window is still showing, this means that this attempt // to close the window was cancelled by the user - so abort the // quit operation if (openWindows[i].isShowing()) return; } } // If we get here, all open windows have been successfully closed // (i.e. the user has not cancelled an offer to save any of them). // Thus, the application can terminate. System.exit(0); } } AddressBookExample/Code/Comparators.java 0000700 0000770 0000120 00000005271 10234251020 020774 0 ustar bjork admin 0000000 0000000 // The following comparators should go inside class Person: /** Comparator for comparing two persons by alphabetical order of name */ public static class CompareByName implements Comparator { /** Compare two objects (which must both be Persons) by last name, * with ties broken by first name * * @param person1 the first object * @param person2 the second object * @return a negative number if person1 belongs before person2 in * alphabetical order of name; 0 if they are equal; a * positive number if person1 belongs after person2 * * @exception ClassCastException if either parameter is not a * Person object */ public int compare(Object person1, Object person2) { int compareByLast = ((Person) person1).getLastName().compareTo( ((Person) person2).getLastName()); if (compareByLast != 0) return compareByLast; else return ((Person) person1).getFirstName().compareTo( ((Person) person2).getFirstName()); } /** Compare two objects (which must both be Persons) by name * * @param person1 the first object * @param person2 the second object * @return true if they have the same name, false if they do not * * @exception ClassCastException if either parameter is not a * Person object */ public boolean equals(Object person1, Object person2) { return compare(person1, person2) == 0; } } /** Comparator for comparing two persons by order of zip code */ public static class CompareByZip implements Comparator { /** Compare two objects (which must both be Persons) by zip * * @param person1 the first object * @param person2 the second object * @return a negative number if person1 belongs before person2 in * order of zip; 0 if they are equal; a positive number if * person1 belongs after person2 * * @exception ClassCastException if either parameter is not a * Person object */ public int compare(Object person1, Object person2) { int compareByZip = ((Person) person1).getZip().compareTo( ((Person) person2).getZip()); if (compareByZip != 0) return compareByZip; else return new CompareByName().compare(person1, person2); } /** Compare two objects (which must both be Persons) by zip * * @param person1 the first object * @param person2 the second object * @return true if they have the same zip, false if they do not * * @exception ClassCastException if either parameter is not a * Person object */ public boolean equals(Object person1, Object person2) { return compare(person1, person2) == 0; } } AddressBookExample/Code/MultiInputPane.java 0000700 0000770 0000120 00000011634 10234251021 021421 0 ustar bjork admin 0000000 0000000 /* * MultiInputPane.java * * Copyright (c) 2004, 2005 - Russell C. Bjork */ import javax.swing.*; import java.awt.*; import java.awt.event.*; /** This is a utility class for displaying a dialog that asks for multiple values. * Based on ideas in Wu's javabook.MultiInputBox class and on ideas in * javax.swing.JOptionPane */ public class MultiInputPane extends JOptionPane { /** Pop up a dialog asking for multiple items of input * * @param parentComponent the parent Component of the dialog that is shown * @param prompts the prompts to display * @param initialValues the initial values to display for each item - * this parameter can be null, in which case no initial values * are specified; or individual elements can be null, * indicating that no initial value is specified for a particular * field * @param title the title for this dialog * @return an array of values corresponding to the various prompts, * or null if the user cancelled */ public static String [] showMultiInputDialog(Component parentComponent, String [] prompts, String [] initialValues, String title) { MultiInputPane pane = new MultiInputPane(prompts, initialValues); JDialog dialog = pane.createDialog(parentComponent, title != null ? title : "MultiInputPane"); dialog.pack(); dialog.show(); if (! pane.ok) return null; String [] results = new String [prompts.length]; for (int i = 0; i < prompts.length; i ++) results[i] = pane.fields[i].getText(); return results; } /** Pop up a dialog asking for multiple items of input * * @param parentComponent the parent Component of the dialog that is shown * @param prompts the prompts to display * @param title the title for this dialog * @return an array of values corresponding to the various prompts, * or null if the user cancelled */ public static String [] showMultiInputDialog(Component parentComponent, String [] prompts, String title) { return showMultiInputDialog(parentComponent, prompts, null, title); } /** Pop up a dialog asking for multiple items of input * * @param parentComponent the parent Component of the dialog that is shown * @param prompts the prompts to display * @param initialValues the initial values to display for each item - * this parameter can be null, in which case no initial values * are specified; or individual elements can be null, * indicating that no initial value is specified for a particular * field * @return an array of values corresponding to the various prompts, * or null if the user cancelled */ public static String [] showMultiInputDialog(Component parentComponent, String [] prompts, String [] initialValues) { return showMultiInputDialog(parentComponent, prompts, initialValues, null); } /** Pop up a dialog asking for multiple items of input * * @param parentComponent the parent Component of the dialog that is shown * @param prompts the prompts to display * @return an array of values corresponding to the various prompts, * or null if the user cancelled */ public static String [] showMultiInputDialog(Component parentComponent, String [] prompts) { return showMultiInputDialog(parentComponent, prompts, null, null); } /** Constructor used by the above * * @param prompts the prompts to display * @param initialValues the initial values to display for each item - * this parameter can be null, in which case no initial values * are specified; or individual elements can be null, * indicating that no initial value is specified for a particular * field */ private MultiInputPane(String [] prompts, String [] initialValues) { super(); removeAll(); setLayout(new GridLayout(prompts.length + 1, 2, 5, 5)); fields = new JTextField[prompts.length]; for (int i = 0; i < prompts.length; i ++) { add(new JLabel(prompts[i])); fields[i] = new JTextField(); add(fields[i]); if (initialValues != null && initialValues[i] != null) fields[i].setText(initialValues[i]); } JPanel okPanel = new JPanel(); JButton okButton = new JButton("OK"); okPanel.add(okButton); add(okPanel); JPanel cancelPanel = new JPanel(); JButton cancelButton = new JButton("Cancel"); cancelPanel.add(cancelButton); add(cancelPanel); okButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { ok = true; getTopLevelAncestor().setVisible(false); } }); cancelButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { getTopLevelAncestor().setVisible(false); } }); } private JTextField [] fields; private boolean ok; } AddressBookExample/Code/.DS_Store 0000700 0000770 0000120 00000014004 10226574324 017334 0 ustar bjork admin 0000000 0000000 Bud1 % @ @ @ @ E % DSDB ` @ @ @ AddressBookExample/Code/AddressBookGUI.java 0000700 0000770 0000120 00000030767 10234251016 021264 0 ustar bjork admin 0000000 0000000 /** * AddressBookGUI.java * * Copyright (c) 2000, 2001, 2005 - Russell C. Bjork * */ import java.awt.*; import java.awt.event.*; import javax.swing.*; import javax.swing.event.*; import java.io.IOException; import java.util.Observer; import java.util.Observable; /** An object of this class allows interaction between the program and the * human user. */ public class AddressBookGUI extends JFrame implements Observer { /** Constructor * * @param controller the controller which performs operations in * response to user gestures on this GUI * @param addressBook the AddressBook this GUI displays */ public AddressBookGUI(final AddressBookController controller, AddressBook addressBook) { this.controller = controller; // Create and add file menu JMenuBar menuBar = new JMenuBar(); JMenu fileMenu = new JMenu("File"); newItem = new JMenuItem("New", 'N'); fileMenu.add(newItem); openItem = new JMenuItem("Open...", 'O'); fileMenu.add(openItem); fileMenu.addSeparator(); saveItem = new JMenuItem("Save", 'S'); fileMenu.add(saveItem); saveAsItem = new JMenuItem("Save As..."); fileMenu.add(saveAsItem); fileMenu.addSeparator(); printItem = new JMenuItem("Print", 'P'); fileMenu.add(printItem); fileMenu.addSeparator(); quitItem = new JMenuItem("Quit", 'Q'); fileMenu.add(quitItem); menuBar.add(fileMenu); setJMenuBar(menuBar); // The displayed list of names gets its information from the // address book nameListModel = new NameListModel(); // The nameListModel and saveItem objects must exist before this is done; // but this must be done before the nameList is created setAddressBook(addressBook); // Create and add components for the main window nameList = new JList(nameListModel); JScrollPane listPane = new JScrollPane(nameList); nameList.setVisibleRowCount(10); listPane.setBorder(BorderFactory.createCompoundBorder( BorderFactory.createEmptyBorder(10, 10, 10, 10), BorderFactory.createLineBorder(Color.gray, 1))); getContentPane().add(listPane, BorderLayout.CENTER); JPanel buttonPanel = new JPanel(); addButton = new JButton(" Add "); buttonPanel.add(addButton); editButton = new JButton(" Edit "); buttonPanel.add(editButton); deleteButton = new JButton(" Delete "); buttonPanel.add(deleteButton); sortByNameButton = new JButton("Sort by name"); buttonPanel.add(sortByNameButton); sortByZipButton = new JButton("Sort by ZIP "); buttonPanel.add(sortByZipButton); buttonPanel.setBorder(BorderFactory.createEmptyBorder(5, 10, 10, 10)); getContentPane().add(buttonPanel, BorderLayout.SOUTH); // Add the action listeners for the buttons, menu items, and close box, // and for double-clicking the list addButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { controller.doAdd(AddressBookGUI.this); int index = getAddressBook().getNumberOfPersons() - 1; // This will ensure that the person just added is visible in list nameList.ensureIndexIsVisible(index); } }); editButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { int index = nameList.getSelectedIndex(); if (index < 0) reportError("You must select a person"); else controller.doEdit(AddressBookGUI.this, index); } }); deleteButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { int index = nameList.getSelectedIndex(); if (index < 0) reportError("You must select a person"); else controller.doDelete(AddressBookGUI.this, index); } }); sortByNameButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { controller.doSortByName(AddressBookGUI.this); } }); sortByZipButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { controller.doSortByZip(AddressBookGUI.this); } }); newItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { try { if (getAddressBook().getChangedSinceLastSave()) controller.doOfferSaveChanges(AddressBookGUI.this); controller.doNew(AddressBookGUI.this); } catch(IOException exception) { reportError("Problem writing the file: " + exception); } catch(InterruptedException exception) { // Thrown if user cancels a save or a file dialog - can be ignored } catch(SecurityException exception) { // Thrown if security manager disallows the operation - // will always happen in an applet reportError("Operation disallowed: " + exception); } } }); openItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { try { if (getAddressBook().getChangedSinceLastSave()) controller.doOfferSaveChanges(AddressBookGUI.this); controller.doOpen(AddressBookGUI.this); } catch(IOException exception) { reportError("Problem reading or writing the file: " + exception); } catch(InterruptedException exception) { // Thrown if user cancels a save or a file dialog - can be ignored } catch(SecurityException exception) { // Thrown if security manager disallows the operation - // will always happen in an applet reportError("Operation disallowed: " + exception); } catch(Exception exception) { // Any other case means the file did not contain an // address book reportError("This file did not contain an address book"); } } }); saveItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { try { controller.doSave(AddressBookGUI.this); } catch(IOException exception) { reportError("Problem writing the file: " + exception); } catch(InterruptedException exception) { // Thrown if user cancels a file dialog - can be ignored } catch(SecurityException exception) { // Thrown if security manager disallows the operation - // will always happen in an applet reportError("Operation disallowed: " + exception); } } }); saveAsItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { try { controller.doSaveAs(AddressBookGUI.this); } catch(IOException exception) { reportError("Problem writing the file: " + exception); } catch(InterruptedException exception) { // Thrown if user cancels a file dialog - can be ignored } catch(SecurityException exception) { // Thrown if security manager disallows the operation - // will always happen in an applet reportError("Operation disallowed: " + exception); } } }); printItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { controller.doPrint(AddressBookGUI.this); } }); quitItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { AddressBookApplication.quitApplication(); } }); setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { try { if (getAddressBook().getChangedSinceLastSave()) controller.doOfferSaveChanges(AddressBookGUI.this); dispose(); if (Frame.getFrames().length == 0) AddressBookApplication.quitApplication(); } catch(IOException exception) { reportError("Problem writing the file: " + exception); } catch(InterruptedException exception) { // Thrown if user cancels a file dialog - can be ignored } catch(SecurityException exception) { // Thrown if security manager disallows the operation - // will always happen in an applet reportError("Operation disallowed: " + exception); } } }); // The following is adapted from an example in the documentation // for class JList. It invokes the controller's doEdit method // if the user double clicks a name. nameList.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent e) { if (e.getClickCount() == 2) { int index = nameList.locationToIndex(e.getPoint()); controller.doEdit(AddressBookGUI.this, index); } } }); pack(); } /** Accessor for the address book this GUI displays * * @return the current address book for this GUI */ public AddressBook getAddressBook() { return addressBook; } /** Mutator to change the address book this GUI displays * * @param addressBook the new address book for this GUI */ public void setAddressBook(AddressBook addressBook) { if (this.addressBook != null) this.addressBook.deleteObserver(this); this.addressBook = addressBook; addressBook.addObserver(this); update(addressBook, null); } /** Report an error to the user * * @param message the message to display */ public void reportError(String message) { JOptionPane.showMessageDialog(this, message, "Error message", JOptionPane.ERROR_MESSAGE); } /** Method required by the Observer interface - update the display * in response to any change in the address book */ public void update(Observable o, Object arg) { if (o == addressBook) { setTitle(addressBook.getTitle()); saveItem.setEnabled(addressBook.getChangedSinceLastSave()); nameListModel.contentsChanged(); } } // GUI components and menu items private NameListModel nameListModel; private JList nameList; private JButton addButton, editButton, deleteButton, sortByNameButton, sortByZipButton; private JMenuItem newItem, openItem, saveItem, saveAsItem, printItem, quitItem; // The controller that performs operations in response to user gestures private AddressBookController controller; // The address book this GUI displays / operates on private AddressBook addressBook; /** Class used for the model for the list of persons in the address book */ private class NameListModel extends AbstractListModel { /** Report that the contents of the list have changed */ void contentsChanged() { super.fireContentsChanged(this, 0, 0); } // Implementation of abstract methods of the base class public Object getElementAt(int index) { return getAddressBook().getFullNameOfPerson(index); } public int getSize() { return getAddressBook().getNumberOfPersons(); } } } AddressBookExample/Sequences.html 0000700 0000770 0000120 00000010407 10226603605 017616 0 ustar bjork admin 0000000 0000000
Each of the use cases discovered in the analysis of the system will be realized by a sequence of operations involving the various objects comprising the system.
Page of links for non frames-enabled browsers.
(Links are only furnished for classes identified during analysis)