We shall use the address-book family of projects to illustrate some of the principles of error reporting and error handling that arise in many applications. The projects represent an appli- cation that stores personal-contact details—name, address, and phone number—for an arbi- trary number of people. Such a contacts list might be used on a mobile phone or in an e-mail program, for instance. The contact details are indexed in the address book by both name and phone number. The main classes we shall be discussing are AddressBook (Code 12.1) and ContactDetails. In addition, the AddressBookDemo class is provided as a convenient means of setting up an initial address book with some sample data.
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.TreeSet;
/**
* A class to maintain an arbitrary number of contact details.
* Details are indexed by both name and phone number.
* @author David J. Barnes and Michael Kửlling.
* @version 2011.07.31 */
public class AddressBook {
// Storage for an arbitrary number of details.
private TreeMap<String, ContactDetails> book;
private int numberOfEntries;
/**
* Perform any initialization for the address book.
*/
public AddressBook() {
book = new TreeMap<String, ContactDetails>();
numberOfEntries = 0;
} /**
* Look up a name or phone number and return the * corresponding contact details.
Code 12.1 TheAddressBook class
12.1 Theaddress-book project | 415
* @param key The name or number to be looked up.
* @return The details corresponding to the key.
*/
public ContactDetails getDetails(String key) {
return book.get(key);
} /**
* Return whether or not the current key is in use.
* @param key The name or number to be looked up.
* @return true if the key is in use, false otherwise.
*/
public boolean keyInUse(String key) {
return book.containsKey(key);
} /**
* Add a new set of details to the address book.
* @param details The details to associate with the person.
*/
public void addDetails(ContactDetails details) {
book.put(details.getName(), details);
book.put(details.getPhone(), details);
numberOfEntries++;
} /**
* Change the details previously stored under the given key.
* @param oldKey One of the keys used to store the details.
* @param details The replacement details.
*/
public void changeDetails(String oldKey,
ContactDetails details) {
removeDetails(oldKey);
addDetails(details);
} /**
* Search for all details stored under a key that starts with * the given prefix.
* @param keyPrefix The key prefix to search on.
* @return An array of those details that have been found.
*/
Code 12.1 continued TheAddressBook class
public ContactDetails[] search(String keyPrefix) {
List<ContactDetails> matches =
new LinkedList<ContactDetails>();
// Find keys that are equal-to or greater-than the prefix.
SortedMap<String, ContactDetails> tail = book.tailMap(keyPrefix);
Iterator<String> it = tail.keySet().iterator();
boolean endOfSearch = false;
while(!endOfSearch && it.hasNext()) { String key = it.next();
if(key.startsWith(keyPrefix)) { matches.add(book.get(key));
} else {
// As the list is sorted, no more will be found.
endOfSearch = true; }
}
ContactDetails[] results =
new ContactDetails[matches.size()];
matches.toArray(results);
return results;
} /**
* Return the number of entries currently in the * address book.
* @return The number of entries.
*/
public int getNumberOfEntries() {
return numberOfEntries;
} /**
* Remove the entry with the given key from the address book.
* @param key One of the keys of the entry to be removed.
*/
public void removeDetails(String key) {
ContactDetails details = book.get(key);
book.remove(details.getName());
book.remove(details.getPhone());
numberOfEntries--;
} Code 12.1
continued TheAddressBook class
12.1 Theaddress-book project | 417
/**
* Return all the contact details, sorted according * to the sort order of the ContactDetails class.
* @return A sorted list of the details.
*/
public String listDetails() {
// Because each entry is stored under two keys, it is // necessary to build a set of the ContactDetails.
// This eliminates duplicates.
StringBuilder allEntries = new StringBuilder();
Set<ContactDetails> sortedDetails =
new TreeSet<ContactDetails>(book.values());
for(ContactDetails details : sortedDetails) { allEntries.append(details);
allEntries.append('\n');
allEntries.append('\n');
}
return allEntries.toString();
} } Code 12.1
continued TheAddressBook class
New details can be stored in the address book via its addDetails method. This assumes that the details represent a new contact and not a change of details for an existing one. To cover the latter case, the changeDetails method removes an old entry and replaces it with the revised details. The address book provides two ways to retrieve entries: the getDetails method takes a name or phone number as the key and returns the matching details; the search method returns an array of all those details that start with a given search string (for instance, the search string"08459" would return all entries with phone numbers having that area prefix).
There are two introductory versions of the address-book project for you to explore. Both provide access to the same version of AddressBook, as shown in Code 12.1. The address- book-v1t project provides a text-based user interface, similar in style to the interface of the zuul game discussed in Chapter 6. Commands are currently available to list the address book’s con- tents, search it, and add a new entry. Probably more interesting as an interface, however, is the address-book-v1g version, which incorporates a simple GUI. Experiment with both versions to gain some experience with what the application can do.
Exercise 12.1 Open the address-book-v1g project and create an AddressBookDemo ob- ject. Call its showInterface method to display the GUI and interact with the sample address book.
Exercise 12.2 Repeat your experimentation with the text interface of the address-book-v1t project.