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.\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
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,155 @@
import java.io.Serializable;
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 implements Serializable
{
// 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) {
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.
*/
public void changeDetails(String oldKey,
ContactDetails details)
{
if(keyInUse(oldKey) && details != null) {
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.
*/
public void removeDetails(String key)
{
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,8 @@
#BlueJ class context
comment0.params=
comment0.target=AddressBookDemo()
comment0.text=\n\ Setup\ an\ AddressBook\ with\ sample\ data.\n\ The\ address\ book\ can\ be\ retrieved\ using\ the\ getBook\ method.\ \n
comment1.params=
comment1.target=AddressBook\ getBook()
comment1.text=\n\ @return\ The\ sample\ address\ book.\n
numComments=2

View File

@@ -0,0 +1,41 @@
/**
* Provide a simple demonstration of the AddressBook class.
* Sample data is added to the address book.
*
* @author David J. Barnes and Michael Kölling.
* @version 2016.02.29
*/
public class AddressBookDemo
{
private AddressBook book;
/**
* Setup an AddressBook with sample data.
* The address book can be retrieved using the getBook method.
*/
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);
}
}
/**
* @return The sample address book.
*/
public AddressBook getBook()
{
return book;
}
}

View File

@@ -0,0 +1,20 @@
#BlueJ class context
comment0.params=book
comment0.target=AddressBookFileHandler(AddressBook)
comment0.text=\n\ Constructor\ for\ objects\ of\ class\ FileHandler.\n\ @param\ book\ The\ address\ book\ to\ use.\n
comment1.params=keyPrefix
comment1.target=void\ saveSearchResults(java.lang.String)
comment1.text=\n\ Save\ the\ results\ of\ an\ address-book\ search\ to\n\ the\ file\ "results.txt"\ in\ the\ project\ folder.\n\ @param\ keyPrefix\ The\ key\ prefix\ to\ search\ on.\n
comment2.params=
comment2.target=void\ showSearchResults()
comment2.text=\n\ Show\ the\ results\ from\ the\ most-recent\ call\ to\n\ saveSearchResults.\ As\ output\ is\ to\ the\ console,\ any\n\ problems\ are\ reported\ directly\ by\ this\ method.\n
comment3.params=filename
comment3.target=void\ addEntriesFromFile(java.lang.String)
comment3.text=\n\ Add\ further\ entries\ to\ the\ address\ book,\ from\ a\ text\ file.\n\ The\ file\ is\ assumed\ to\ contain\ one\ element\ per\ line,\n\ plus\ a\ blank\ line,\ for\ each\ entry\:\n\ \ \ \ \ name\ \\n\ phone\ \\n\ address\ \\n\ \\n\n\ A\ line\ may\ be\ blank\ if\ that\ part\ of\ the\ details\ is\ missing.\n\ @param\ filename\ The\ text\ file\ containing\ the\ details.\n\ @throws\ IOException\ On\ input\ failure.\n
comment4.params=sourceFile
comment4.target=AddressBook\ readFromFile(java.lang.String)
comment4.text=\n\ Read\ the\ binary\ version\ of\ an\ address\ book\ from\ the\ given\ file.\n\ If\ the\ file\ name\ is\ not\ an\ absolute\ path,\ then\ it\ is\ assumed\n\ to\ be\ relative\ to\ the\ current\ project\ folder.\n\ @param\ sourceFile\ The\ file\ from\ where\ the\ details\ are\ to\ be\ read.\n\ @return\ The\ address\ book\ object.\n\ @throws\ IOException\ If\ the\ reading\ process\ fails\ for\ any\ reason.\n
comment5.params=destinationFile
comment5.target=void\ saveToFile(java.lang.String)
comment5.text=\n\ Save\ a\ binary\ version\ of\ the\ address\ book\ to\ the\ given\ file.\n\ If\ the\ file\ name\ is\ not\ an\ absolute\ path,\ then\ it\ is\ assumed\n\ to\ be\ relative\ to\ the\ current\ project\ folder.\n\ @param\ destinationFile\ The\ file\ where\ the\ details\ are\ to\ be\ saved.\n\ @throws\ IOException\ If\ the\ saving\ process\ fails\ for\ any\ reason.\n
numComments=6

View File

@@ -0,0 +1,169 @@
import java.io.*;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.*;
/**
* Provide a range of file-handling operations on an AddressBook.
* These methods demonstrate a range of basic features of the
* java.io package.
*
* @author David J. Barnes and Michael Kölling.
* @version 2016.02.29
*/
public class AddressBookFileHandler
{
// The address book on which i/o operations are performed.
private AddressBook book;
// The name of a file used to store search results.
private static final String RESULTS_FILE = "results.txt";
/**
* Constructor for objects of class FileHandler.
* @param book The address book to use.
*/
public AddressBookFileHandler(AddressBook book)
{
this.book = book;
}
/**
* Save the results of an address-book search to
* the file "results.txt" in the project folder.
* @param keyPrefix The key prefix to search on.
*/
public void saveSearchResults(String keyPrefix) throws IOException
{
Path resultsFile = Paths.get(RESULTS_FILE).toAbsolutePath();
ContactDetails[] results = book.search(keyPrefix);
FileWriter writer = new FileWriter(resultsFile.toString());
for(ContactDetails details : results) {
writer.write(details.toString());
writer.write('\n');
writer.write('\n');
}
writer.close();
}
/**
* Show the results from the most-recent call to
* saveSearchResults. As output is to the console, any
* problems are reported directly by this method.
*/
public void showSearchResults()
{
BufferedReader reader = null;
try {
Path resultsFile = Paths.get(RESULTS_FILE).toAbsolutePath();
reader = new BufferedReader(new FileReader(resultsFile.toString()));
System.out.println("Results ...");
String line;
line = reader.readLine();
while(line != null) {
System.out.println(line);
line = reader.readLine();
}
System.out.println();
}
catch(FileNotFoundException e) {
System.out.println("Unable to find the file: " +
RESULTS_FILE);
}
catch(IOException e) {
System.out.println("Error encountered reading the file: " +
RESULTS_FILE);
}
finally {
if(reader != null) {
// Catch any exception, but nothing can be done
// about it.
try {
reader.close();
}
catch(IOException e) {
System.out.println("Error on closing: " +
RESULTS_FILE);
}
}
}
}
/**
* Add further entries to the address book, from a text file.
* The file is assumed to contain one element per line,
* plus a blank line, for each entry:
* name \n phone \n address \n \n
* A line may be blank if that part of the details is missing.
* @param filename The text file containing the details.
* @throws IOException On input failure.
*/
public void addEntriesFromFile(String filename) throws IOException
{
// Make sure the file can be found.
URL resource = getClass().getResource(filename);
if(resource == null) {
throw new FileNotFoundException(filename);
}
filename = resource.getFile();
BufferedReader reader = new BufferedReader(
new FileReader(filename));
String name;
name = reader.readLine();
while(name != null) {
String phone = reader.readLine();
String address = reader.readLine();
// Discard the separating blank line.
reader.readLine();
book.addDetails(new ContactDetails(name, phone,
address));
name = reader.readLine();
}
reader.close();
}
/**
* Read the binary version of an address book from the given file.
* If the file name is not an absolute path, then it is assumed
* to be relative to the current project folder.
* @param sourceFile The file from where the details are to be read.
* @return The address book object.
* @throws IOException If the reading process fails for any reason.
*/
public AddressBook readFromFile(String sourceFile)
throws IOException, ClassNotFoundException
{
// Make sure the file can be found.
URL resource = getClass().getResource(sourceFile);
if(resource == null) {
throw new FileNotFoundException(sourceFile);
}
try {
File source = new File(resource.toURI());
ObjectInputStream is = new ObjectInputStream(
new FileInputStream(source));
AddressBook savedBook = (AddressBook) is.readObject();
is.close();
return savedBook;
}
catch(URISyntaxException e) {
throw new IOException("Unable to make a valid filename for " +
sourceFile);
}
}
/**
* Save a binary version of the address book to the given file.
* If the file name is not an absolute path, then it is assumed
* to be relative to the current project folder.
* @param destinationFile The file where the details are to be saved.
* @throws IOException If the saving process fails for any reason.
*/
public void saveToFile(String destinationFile) throws IOException
{
Path destination = Paths.get(destinationFile).toAbsolutePath();
ObjectOutputStream os = new ObjectOutputStream(
new FileOutputStream(destination.toString()));
os.writeObject(book);
os.close();
}
}

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
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,125 @@
import java.io.Serializable;
/**
* Name, address and telephone number details.
*
* @author David J. Barnes and Michael Kölling.
* @version 2016.02.29
*/
public class ContactDetails implements Comparable<ContactDetails>, Serializable
{
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.
*/
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();
}
/**
* @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,28 @@
Project: address-book-io
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.
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 use its getBook method.
Create an AddressBookFileHandler to illustrate some basic
input-output operations on an AddressBook.
User instructions:
+ Search results are saved to "results.txt" in the project folder.
+ The file "sample.txt", in the project, folder contains a sample
entry that can be added, using the addEntriesFromFile of
the AddressBookFileHandler.
+ A complete address book object may be saved, in binary form,
using the saveToFile method. This may be read in again with
readFromFile.

View File

@@ -0,0 +1,83 @@
#BlueJ package file
dependency1.from=AddressBookFileHandler
dependency1.to=AddressBook
dependency1.type=UsesDependency
dependency2.from=AddressBookFileHandler
dependency2.to=ContactDetails
dependency2.type=UsesDependency
dependency3.from=AddressBook
dependency3.to=ContactDetails
dependency3.type=UsesDependency
dependency4.from=AddressBookDemo
dependency4.to=AddressBook
dependency4.type=UsesDependency
dependency5.from=AddressBookDemo
dependency5.to=ContactDetails
dependency5.type=UsesDependency
objectbench.height=76
objectbench.width=842
package.editor.height=447
package.editor.width=734
package.editor.x=70
package.editor.y=80
package.numDependencies=5
package.numTargets=4
package.showExtends=true
package.showUses=true
project.charset=UTF-8
readme.editor.height=586
readme.editor.width=821
readme.editor.x=42
readme.editor.y=23
target1.editor.height=761
target1.editor.width=894
target1.editor.x=53
target1.editor.y=39
target1.height=60
target1.name=AddressBook
target1.naviview.expanded=true
target1.showInterface=false
target1.type=ClassTarget
target1.typeParameters=
target1.width=140
target1.x=220
target1.y=160
target2.editor.height=715
target2.editor.width=874
target2.editor.x=50
target2.editor.y=60
target2.height=60
target2.name=ContactDetails
target2.naviview.expanded=true
target2.showInterface=false
target2.type=ClassTarget
target2.typeParameters=
target2.width=150
target2.x=340
target2.y=260
target3.editor.height=747
target3.editor.width=842
target3.editor.x=50
target3.editor.y=53
target3.height=60
target3.name=AddressBookDemo
target3.naviview.expanded=true
target3.showInterface=false
target3.type=ClassTarget
target3.typeParameters=
target3.width=150
target3.x=90
target3.y=60
target4.editor.height=719
target4.editor.width=819
target4.editor.x=43
target4.editor.y=23
target4.height=60
target4.name=AddressBookFileHandler
target4.naviview.expanded=true
target4.showInterface=false
target4.type=ClassTarget
target4.typeParameters=
target4.width=180
target4.x=470
target4.y=350

View File

@@ -0,0 +1,4 @@
chris
08459 700000
address 7