first commit

This commit is contained in:
Boris
2024-01-15 20:14:10 +00:00
commit 8c81ee28b7
3106 changed files with 474415 additions and 0 deletions

View File

@@ -0,0 +1,29 @@
#BlueJ class context
comment0.params=
comment0.target=AddressBook()
comment0.text=\n\ Perform\ any\ initialization\ for\ the\ address\ book.\n
comment1.params=key
comment1.target=ContactDetails\ getDetails(java.lang.String)
comment1.text=\n\ Look\ up\ a\ name\ or\ phone\ number\ and\ return\ the\n\ corresponding\ contact\ details.\n\ @param\ key\ The\ name\ or\ number\ to\ be\ looked\ up.\n\ @return\ The\ details\ corresponding\ to\ the\ key.\n
comment2.params=key
comment2.target=boolean\ keyInUse(java.lang.String)
comment2.text=\n\ Return\ whether\ or\ not\ the\ current\ key\ is\ in\ use.\n\ @param\ key\ The\ name\ or\ number\ to\ be\ looked\ up.\n\ @return\ true\ if\ the\ key\ is\ in\ use,\ false\ otherwise.\n
comment3.params=details
comment3.target=void\ addDetails(ContactDetails)
comment3.text=\n\ Add\ a\ new\ set\ of\ details\ to\ the\ address\ book.\n\ @param\ details\ The\ details\ to\ associate\ with\ the\ person.\n
comment4.params=oldKey\ details
comment4.target=void\ changeDetails(java.lang.String,\ ContactDetails)
comment4.text=\n\ Change\ the\ details\ previously\ stored\ under\ the\ given\ key.\n\ @param\ oldKey\ One\ of\ the\ keys\ used\ to\ store\ the\ details.\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ This\ should\ be\ a\ key\ that\ is\ currently\ in\ use.\n\ @param\ details\ The\ replacement\ details.\ Must\ not\ be\ null.\n\ @throws\ IllegalArgumentException\ If\ either\ argument\ is\ null.\n
comment5.params=keyPrefix
comment5.target=ContactDetails[]\ search(java.lang.String)
comment5.text=\n\ Search\ for\ all\ details\ stored\ under\ a\ key\ that\ starts\ with\n\ the\ given\ prefix.\n\ @param\ keyPrefix\ The\ key\ prefix\ to\ search\ on.\ This\ may\ be\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ of\ zero\ length,\ but\ must\ not\ be\ null.\n\ @return\ An\ array\ of\ those\ details\ that\ have\ been\ found.\n
comment6.params=
comment6.target=int\ getNumberOfEntries()
comment6.text=\n\ Return\ the\ number\ of\ entries\ currently\ in\ the\n\ address\ book.\n\ @return\ The\ number\ of\ entries.\n
comment7.params=key
comment7.target=void\ removeDetails(java.lang.String)
comment7.text=\n\ Remove\ the\ entry\ with\ the\ given\ key\ from\ the\ address\ book.\n\ The\ key\ should\ be\ one\ that\ is\ currently\ in\ use.\n\ @param\ key\ One\ of\ the\ keys\ of\ the\ entry\ to\ be\ removed.\n\ @throws\ IllegalArgumentException\ If\ the\ key\ is\ null.\n
comment8.params=
comment8.target=java.lang.String\ listDetails()
comment8.text=\n\ Return\ all\ the\ contact\ details,\ sorted\ according\n\ to\ the\ sort\ order\ of\ the\ ContactDetails\ class.\n\ @return\ A\ sorted\ list\ of\ the\ details.\n
numComments=9

View File

@@ -0,0 +1,166 @@
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 2016.02.29
*/
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<>();
numberOfEntries = 0;
}
/**
* Look up a name or phone number and return the
* corresponding contact details.
* @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)
{
if(details == null) {
throw new IllegalArgumentException("Null details passed to addDetails.");
}
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.
This should be a key that is currently in use.
* @param details The replacement details. Must not be null.
* @throws IllegalArgumentException If either argument is null.
*/
public void changeDetails(String oldKey,
ContactDetails details)
{
if(details == null) {
throw new IllegalArgumentException("Null details passed to changeDetails.");
}
if(oldKey == null){
throw new IllegalArgumentException("Null key passed to changeDetails.");
}
if(keyInUse(oldKey)){
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. This may be
* of zero length, but must not be null.
* @return An array of those details that have been found.
*/
public ContactDetails[] search(String keyPrefix)
{
// Build a list of the matches.
List<ContactDetails> matches = new LinkedList<>();
if(keyPrefix != null) {
// Find keys that are equal-to or greater-than the prefix.
SortedMap<String, ContactDetails> tail = book.tailMap(keyPrefix);
Iterator<String> it = tail.keySet().iterator();
// Stop when we find a mismatch.
boolean endOfSearch = false;
while(!endOfSearch && it.hasNext()) {
String key = it.next();
if(key.startsWith(keyPrefix)) {
matches.add(book.get(key));
}
else {
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.
* The key should be one that is currently in use.
* @param key One of the keys of the entry to be removed.
* @throws IllegalArgumentException If the key is null.
*/
public void removeDetails(String key)
{
if(key == null){
throw new IllegalArgumentException("Null key passed to removeDetails.");
}
if(keyInUse(key)) {
ContactDetails details = book.get(key);
book.remove(details.getName());
book.remove(details.getPhone());
numberOfEntries--;
}
}
/**
* 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<>(book.values());
for(ContactDetails details : sortedDetails) {
allEntries.append(details).append("\n\n");
}
return allEntries.toString();
}
}

View File

@@ -0,0 +1,11 @@
#BlueJ class context
comment0.params=
comment0.target=AddressBookDemo()
comment0.text=\n\ Setup\ an\ AddressBook\ with\ sample\ data.\n\ The\ address\ book\ is\ passed\ to\ a\ GUI\ to\ provide\n\ a\ view\ of\ the\ data.\n
comment1.params=
comment1.target=void\ showInterface()
comment1.text=\n\ Allow\ the\ user\ to\ interact\ with\ the\ address\ book.\n
comment2.params=
comment2.target=AddressBook\ getBook()
comment2.text=\n\ @return\ The\ sample\ address\ book.\n
numComments=3

View File

@@ -0,0 +1,53 @@
/**
* Provide a simple demonstration of the AddressBook class.
* Sample data is added to the address book,
* and a text interface is provided.
*
* @author David J. Barnes and Michael Kölling.
* @version 2016.02.29
*/
public class AddressBookDemo
{
private AddressBook book;
private AddressBookTextInterface interaction;
/**
* Setup an AddressBook with sample data.
* The address book is passed to a GUI to provide
* a view of the data.
*/
public AddressBookDemo()
{
ContactDetails[] sampleDetails = {
new ContactDetails("david", "08459 100000", "address 1"),
new ContactDetails("michael", "08459 200000", "address 2"),
new ContactDetails("john", "08459 300000", "address 3"),
new ContactDetails("helen", "08459 400000", "address 4"),
new ContactDetails("emma", "08459 500000", "address 5"),
new ContactDetails("kate", "08459 600000", "address 6"),
new ContactDetails("chris", "08459 700000", "address 7"),
new ContactDetails("ruth", "08459 800000", "address 8"),
};
book = new AddressBook();
for(ContactDetails details : sampleDetails) {
book.addDetails(details);
}
interaction = new AddressBookTextInterface(book);
}
/**
* Allow the user to interact with the address book.
*/
public void showInterface()
{
interaction.run();
}
/**
* @return The sample address book.
*/
public AddressBook getBook()
{
return book;
}
}

View File

@@ -0,0 +1,26 @@
#BlueJ class context
comment0.params=book
comment0.target=AddressBookTextInterface(AddressBook)
comment0.text=\n\ Constructor\ for\ objects\ of\ class\ AddressBookTextInterface\n\ @param\ book\ The\ address\ book\ to\ be\ manipulated.\n
comment1.params=
comment1.target=void\ run()
comment1.text=\n\ Read\ a\ series\ of\ commands\ from\ the\ user\ to\ interact\n\ with\ the\ address\ book.\ Stop\ when\ the\ user\ types\ 'quit'.\n
comment2.params=
comment2.target=void\ add()
comment2.text=\n\ Add\ a\ new\ entry.\n
comment3.params=
comment3.target=void\ get()
comment3.text=\n\ Find\ an\ entry\ matching\ a\ key.\n
comment4.params=
comment4.target=void\ remove()
comment4.text=\n\ Remove\ an\ entry\ matching\ a\ key.\n
comment5.params=
comment5.target=void\ find()
comment5.text=\n\ Find\ entries\ matching\ a\ key\ prefix.\n
comment6.params=
comment6.target=void\ help()
comment6.text=\n\ List\ the\ available\ commands.\n
comment7.params=
comment7.target=void\ list()
comment7.text=\n\ List\ the\ address\ book's\ contents.\n
numComments=8

View File

@@ -0,0 +1,133 @@
/**
* Provide a textual interface to an AddressBook.
* Different commands provide access to the data in the address book.
*
* One to search the address book.
*
* One to allow a set of contact details to be entered.
*
* One to show all the entries in the book.
*
* @author David J. Barnes and Michael Kölling.
* @version 2016.02.29
*/
public class AddressBookTextInterface
{
// The address book to be viewed and manipulated.
private AddressBook book;
// A parser for handling user commands.
private Parser parser;
/**
* Constructor for objects of class AddressBookTextInterface
* @param book The address book to be manipulated.
*/
public AddressBookTextInterface(AddressBook book)
{
this.book = book;
parser = new Parser();
}
/**
* Read a series of commands from the user to interact
* with the address book. Stop when the user types 'quit'.
*/
public void run()
{
System.out.println("Address Book.");
System.out.println("Type 'help' for a list of commands.");
String command;
do{
command = parser.getCommand();
if(command.equals("add")){
add();
}
else if(command.equals("get")){
get();
}
else if(command.equals("list")){
list();
}
else if(command.equals("search")){
find();
}
else if(command.equals("remove")){
remove();
}
else if(command.equals("help")){
help();
}
else{
// Do nothing.
}
} while(!(command.equals("quit")));
System.out.println("Goodbye.");
}
/**
* Add a new entry.
*/
private void add()
{
System.out.print("Name: ");
String name = parser.readLine();
System.out.print("Phone: ");
String phone = parser.readLine();
System.out.print("Address: ");
String address = parser.readLine();
book.addDetails(new ContactDetails(name, phone, address));
}
/**
* Find an entry matching a key.
*/
private void get()
{
System.out.println("Type the key of the entry.");
String key = parser.readLine();
ContactDetails result = book.getDetails(key);
System.out.println(result);
}
/**
* Remove an entry matching a key.
*/
private void remove()
{
System.out.println("Type the key of the entry.");
String key = parser.readLine();
book.removeDetails(key);
}
/**
* Find entries matching a key prefix.
*/
private void find()
{
System.out.println("Type a prefix of the key to be found.");
String prefix = parser.readLine();
ContactDetails[] results = book.search(prefix);
for(int i = 0; i < results.length; i++){
System.out.println(results[i]);
System.out.println("=====");
}
}
/**
* List the available commands.
*/
private void help()
{
parser.showCommands();
}
/**
* List the address book's contents.
*/
private void list()
{
System.out.println(book.listDetails());
}
}

View File

@@ -0,0 +1,11 @@
#BlueJ class context
comment0.params=
comment0.target=CommandWords()
comment0.text=\n\ Constructor\ for\ CommandWords\n
comment1.params=aString
comment1.target=boolean\ isCommand(java.lang.String)
comment1.text=\n\ Check\ whether\ a\ given\ String\ is\ a\ valid\ command\ word.\n\ @param\ aString\ The\ string\ to\ be\ checked.\n\ @return\ true\ if\ it\ is\ valid,\ false\ if\ it\ isn't.\n
comment2.params=
comment2.target=void\ showAll()
comment2.text=\n\ Print\ all\ valid\ commands\ to\ System.out.\n
numComments=3

View File

@@ -0,0 +1,49 @@
/**
* This class holds an enumeration of all command words known
* to the program.
*
* @author David J. Barnes and Michael Kölling.
* @version 2016.02.29
*/
public class CommandWords
{
// a constant array that holds all valid command words
private static final String validCommands[] = {
"add", "get", "search", "list", "remove", "help", "quit",
};
/**
* Constructor for CommandWords
*/
public CommandWords()
{
}
/**
* Check whether a given String is a valid command word.
* @param aString The string to be checked.
* @return true if it is valid, false if it isn't.
*/
public boolean isCommand(String aString)
{
if(aString != null){
for(int i = 0; i < validCommands.length; i++) {
if(validCommands[i].equals(aString))
return true;
}
}
// if we get here, the string was not found in the commands
return false;
}
/**
* Print all valid commands to System.out.
*/
public void showAll()
{
for(String command : validCommands) {
System.out.print(command + " ");
}
System.out.println();
}
}

View File

@@ -0,0 +1,26 @@
#BlueJ class context
comment0.params=name\ phone\ address
comment0.target=ContactDetails(java.lang.String,\ java.lang.String,\ java.lang.String)
comment0.text=\n\ Set\ up\ the\ contact\ details.\ All\ details\ are\ trimmed\ to\ remove\n\ trailing\ white\ space.\n\ @param\ name\ The\ name.\n\ @param\ phone\ The\ phone\ number.\n\ @param\ address\ The\ address.\n\ @throws\ IllegalStateException\ If\ both\ name\ and\ phone\ are\ blank.\n
comment1.params=
comment1.target=java.lang.String\ getName()
comment1.text=\n\ @return\ The\ name.\n
comment2.params=
comment2.target=java.lang.String\ getPhone()
comment2.text=\n\ @return\ The\ telephone\ number.\n
comment3.params=
comment3.target=java.lang.String\ getAddress()
comment3.text=\n\ @return\ The\ address.\n
comment4.params=other
comment4.target=boolean\ equals(java.lang.Object)
comment4.text=\n\ Test\ for\ content\ equality\ between\ two\ objects.\n\ @param\ other\ The\ object\ to\ compare\ to\ this\ one.\n\ @return\ true\ if\ the\ argument\ object\ is\ a\ set\n\ \ \ \ \ \ \ \ \ \ \ \ \ \ of\ contact\ details\ with\ matching\ attributes.\n
comment5.params=otherDetails
comment5.target=int\ compareTo(ContactDetails)
comment5.text=\n\ Compare\ these\ details\ against\ another\ set,\ for\ the\ purpose\n\ of\ sorting.\ The\ fields\ are\ sorted\ by\ name,\ phone,\ and\ address.\n\ @param\ otherDetails\ The\ details\ to\ be\ compared\ against.\n\ @return\ a\ negative\ integer\ if\ this\ comes\ before\ the\ parameter,\n\ \ \ \ \ \ \ \ \ zero\ if\ they\ are\ equal\ and\ a\ positive\ integer\ if\ this\n\ \ \ \ \ \ \ \ \ comes\ after\ the\ second.\n
comment6.params=
comment6.target=java.lang.String\ toString()
comment6.text=\n\ @return\ A\ multi-line\ string\ containing\ the\ name,\ phone,\ and\ address.\n
comment7.params=
comment7.target=int\ hashCode()
comment7.text=\n\ Compute\ a\ hashcode\ using\ the\ rules\ to\ be\ found\ in\n\ "Effective\ Java",\ by\ Joshua\ Bloch.\n\ @return\ A\ hashcode\ for\ ContactDetails.\n
numComments=8

View File

@@ -0,0 +1,129 @@
/**
* Name, address and telephone number details.
*
* @author David J. Barnes and Michael Kölling.
* @version 2016.02.29
*/
public class ContactDetails implements Comparable<ContactDetails>
{
private String name;
private String phone;
private String address;
/**
* Set up the contact details. All details are trimmed to remove
* trailing white space.
* @param name The name.
* @param phone The phone number.
* @param address The address.
* @throws IllegalStateException If both name and phone are blank.
*/
public ContactDetails(String name, String phone, String address)
{
// Use blank strings if any of the arguments is null.
if(name == null) {
name = "";
}
if(phone == null) {
phone = "";
}
if(address == null) {
address = "";
}
this.name = name.trim();
this.phone = phone.trim();
this.address = address.trim();
if(this.name.isEmpty() && this.phone.isEmpty()) {
throw new IllegalStateException(
"Either the name or phone must not be blank.");
}
}
/**
* @return The name.
*/
public String getName()
{
return name;
}
/**
* @return The telephone number.
*/
public String getPhone()
{
return phone;
}
/**
* @return The address.
*/
public String getAddress()
{
return address;
}
/**
* Test for content equality between two objects.
* @param other The object to compare to this one.
* @return true if the argument object is a set
* of contact details with matching attributes.
*/
public boolean equals(Object other)
{
if(other instanceof ContactDetails) {
ContactDetails otherDetails = (ContactDetails) other;
return name.equals(otherDetails.getName()) &&
phone.equals(otherDetails.getPhone()) &&
address.equals(otherDetails.getAddress());
}
else {
return false;
}
}
/**
* Compare these details against another set, for the purpose
* of sorting. The fields are sorted by name, phone, and address.
* @param otherDetails The details to be compared against.
* @return a negative integer if this comes before the parameter,
* zero if they are equal and a positive integer if this
* comes after the second.
*/
public int compareTo(ContactDetails otherDetails)
{
int comparison = name.compareTo(otherDetails.getName());
if(comparison != 0){
return comparison;
}
comparison = phone.compareTo(otherDetails.getPhone());
if(comparison != 0){
return comparison;
}
return address.compareTo(otherDetails.getAddress());
}
/**
* @return A multi-line string containing the name, phone, and address.
*/
public String toString()
{
return name + "\n" + phone + "\n" + address;
}
/**
* Compute a hashcode using the rules to be found in
* "Effective Java", by Joshua Bloch.
* @return A hashcode for ContactDetails.
*/
public int hashCode()
{
int code = 17;
code = 37 * code + name.hashCode();
code = 37 * code + phone.hashCode();
code = 37 * code + address.hashCode();
return code;
}
}

View File

@@ -0,0 +1,11 @@
#BlueJ class context
comment0.params=key
comment0.target=NoMatchingDetailsException(java.lang.String)
comment0.text=\n\ Store\ the\ details\ in\ error.\n\ @param\ key\ The\ key\ with\ no\ match.\n
comment1.params=
comment1.target=java.lang.String\ getKey()
comment1.text=\n\ @return\ The\ key\ in\ error.\n
comment2.params=
comment2.target=java.lang.String\ toString()
comment2.text=\n\ @return\ A\ diagnostic\ string\ containing\ the\ key\ in\ error.\n
numComments=3

View File

@@ -0,0 +1,37 @@
/**
* Capture a key that failed to match an entry
* in the address book.
*
* @author David J. Barnes and Michael Kölling.
* @version 2016.02.29
*/
public class NoMatchingDetailsException extends Exception
{
// The key with no match.
private String key;
/**
* Store the details in error.
* @param key The key with no match.
*/
public NoMatchingDetailsException(String key)
{
this.key = key;
}
/**
* @return The key in error.
*/
public String getKey()
{
return key;
}
/**
* @return A diagnostic string containing the key in error.
*/
public String toString()
{
return "No details matching: " + key + " were found.";
}
}

View File

@@ -0,0 +1,13 @@
#BlueJ class context
comment0.params=
comment0.target=Parser()
comment1.params=
comment1.target=java.lang.String\ getCommand()
comment1.text=\n\ Read\ the\ next\ command\ from\ the\ user.\n\ The\ returned\ command\ will\ be\ valid.\n\ @return\ A\ valid\ command.\n
comment2.params=
comment2.target=void\ showCommands()
comment2.text=\n\ Print\ out\ a\ list\ of\ valid\ command\ words.\n
comment3.params=
comment3.target=java.lang.String\ readLine()
comment3.text=\n\ @return\ A\ line\ of\ text\ from\ the\ user.\n
numComments=4

View File

@@ -0,0 +1,65 @@
import java.util.Scanner;
/**
* A class that reads input lines from the user.
* Input is filtered via getCommand for valid commands.
*
* @author David J. Barnes and Michael Kölling.
* @version 2016.02.29
*/
public class Parser
{
// Hold all valid command words.
private CommandWords commands;
private Scanner reader;
public Parser()
{
commands = new CommandWords();
reader = new Scanner(System.in);
}
/**
* Read the next command from the user.
* The returned command will be valid.
* @return A valid command.
*/
public String getCommand()
{
String command = null;
do {
// Print a prompt.
System.out.print("> ");
String word = reader.next();
// Discard the rest of the line.
readLine();
if(commands.isCommand(word)) {
command = word;
}
else{
System.out.println("Unrecognized command: " + word);
System.out.print("Valid commands are: ");
commands.showAll();
}
} while(command == null);
return command;
}
/**
* Print out a list of valid command words.
*/
public void showCommands()
{
commands.showAll();
}
/**
* @return A line of text from the user.
*/
public String readLine()
{
return reader.nextLine();
}
}

View File

@@ -0,0 +1,19 @@
Project: address-book-v3t
Authors: David J. Barnes and Michael Kölling
This project is part of the material for chapter 12 of the book
Objects First with Java - A Practical Introduction using BlueJ
Sixth edition
David J. Barnes and Michael Kölling
Pearson Education, 2016
A simple address-book implementation.
This version includes some argument-validity checking.
How to start this project:
Either: Create an AddressBook object and add
contact details (such as name, address, and phone) to it.
Or: create an AddressBookDemo and call its showInterface method.
This will create a sample AddressBook along with a text
interface for the purposes of interactive experimentation.

View File

@@ -0,0 +1,131 @@
#BlueJ package file
dependency1.from=Parser
dependency1.to=CommandWords
dependency1.type=UsesDependency
dependency2.from=AddressBook
dependency2.to=ContactDetails
dependency2.type=UsesDependency
dependency3.from=AddressBookDemo
dependency3.to=AddressBook
dependency3.type=UsesDependency
dependency4.from=AddressBookDemo
dependency4.to=AddressBookTextInterface
dependency4.type=UsesDependency
dependency5.from=AddressBookDemo
dependency5.to=ContactDetails
dependency5.type=UsesDependency
dependency6.from=AddressBookTextInterface
dependency6.to=AddressBook
dependency6.type=UsesDependency
dependency7.from=AddressBookTextInterface
dependency7.to=Parser
dependency7.type=UsesDependency
dependency8.from=AddressBookTextInterface
dependency8.to=ContactDetails
dependency8.type=UsesDependency
objectbench.height=76
objectbench.width=949
package.editor.height=500
package.editor.width=841
package.editor.x=70
package.editor.y=80
package.numDependencies=8
package.numTargets=7
package.showExtends=true
package.showUses=true
project.charset=UTF-8
readme.editor.height=588
readme.editor.width=813
readme.editor.x=36
readme.editor.y=23
target1.editor.height=735
target1.editor.width=862
target1.editor.x=53
target1.editor.y=23
target1.height=60
target1.name=AddressBook
target1.naviview.expanded=true
target1.showInterface=false
target1.type=ClassTarget
target1.typeParameters=
target1.width=120
target1.x=180
target1.y=220
target2.editor.height=748
target2.editor.width=826
target2.editor.x=50
target2.editor.y=52
target2.height=60
target2.name=ContactDetails
target2.naviview.expanded=true
target2.showInterface=false
target2.type=ClassTarget
target2.typeParameters=
target2.width=130
target2.x=280
target2.y=340
target3.editor.height=744
target3.editor.width=820
target3.editor.x=50
target3.editor.y=56
target3.height=60
target3.name=AddressBookDemo
target3.naviview.expanded=true
target3.showInterface=false
target3.type=ClassTarget
target3.typeParameters=
target3.width=130
target3.x=90
target3.y=30
target4.editor.height=738
target4.editor.width=823
target4.editor.x=153
target4.editor.y=42
target4.height=60
target4.name=NoMatchingDetailsException
target4.naviview.expanded=true
target4.showInterface=false
target4.type=ClassTarget
target4.typeParameters=
target4.width=190
target4.x=590
target4.y=110
target5.editor.height=700
target5.editor.width=900
target5.editor.x=37
target5.editor.y=23
target5.height=60
target5.name=AddressBookTextInterface
target5.naviview.expanded=true
target5.showInterface=false
target5.type=ClassTarget
target5.typeParameters=
target5.width=180
target5.x=360
target5.y=110
target6.editor.height=730
target6.editor.width=843
target6.editor.x=50
target6.editor.y=60
target6.height=60
target6.name=CommandWords
target6.naviview.expanded=true
target6.showInterface=false
target6.type=ClassTarget
target6.typeParameters=
target6.width=140
target6.x=600
target6.y=340
target7.editor.height=712
target7.editor.width=845
target7.editor.x=50
target7.editor.y=60
target7.height=60
target7.name=Parser
target7.naviview.expanded=true
target7.showInterface=false
target7.type=ClassTarget
target7.typeParameters=
target7.width=110
target7.x=510
target7.y=220