/*********************************************** * CS2510 Spring 2011 * Lecture #13.3 * State Chang: list wrapper ***********************************************/ /** Goal: change the phone number for a given person */ import tester.Tester; /* +-----------------+ | ListPersons | +-----------------+ +--| ILoPerson plist | | +-----------------+ v +-----------+ | ILoPerson |<------------+ +-----------+ | +-----------+ | / \ | --- | | | ------------------- | | | | +------------+ +----------------+ | | MTLoObject | | ConsLoObject | | +------------+ +----------------+ | +------------+ +-| Object first | | | | ILoObject rest |-+ | +----------------+ v +-------------+ | Person | +-------------+ | String name | | int phone | +-------------+ */ // to represent a person in a contacts list class Person{ String name; int phone; Person(String name, int phone){ this.name = name; this.phone = phone; } // EFFECT: // change the phone number of this person to the given one void newPhone(int newNumber){ this.phone = newNumber; } // is this the same person as the given person? boolean samePerson(Person that){ return this.name.equals(that.name) && this.phone == that.phone; } } // to represent a mutable list of persons class ListPersons{ ILoPerson plist; ListPersons(ILoPerson plist){ this.plist = plist; } // NOTE: // we have to re-define the methods 'contains' and changePhone' // from the ILoPerson and just delegate to the methods // that are implemented there // does this list contain the given Person? public boolean contains(Person p){ return this.plist.contains(p); } // EFFECT: // change the phone number for the person with the given name // in this list to the given new number public void changePhone(String name, int phone){ this.plist.changePhone(name, phone); } // EFFECT: // add the given person to this list void addPerson(Person p){ this.plist = this.plist.addPerson(p); } // EFFECT: // remove the given person to this list void removePerson(Person p){ this.plist = this.plist.removePerson(p); } } // to represent a list of Person-s interface ILoPerson{ // is the given person in this list? public boolean contains (Person that); // EFFECT: // change the phone number for the given person // in this list to the given number public void changePhone(String name, int phone); // produce a list with the given person added to this list public ILoPerson addPerson(Person p); // produce a list with the given person removed form this list public ILoPerson removePerson(Person p); } // to represent an empty list of person contacts class MtLoPerson implements ILoPerson{ // does thsi empty list contain the given person? public boolean contains (Person that){ return false; } //EFFECT: // change the phone number for the given person // in this list to the given number public void changePhone(String name, int phone){ throw new RuntimeException("No person with the given name in our list"); } // produce a list with the given person added to this list public ILoPerson addPerson(Person p){ return new ConsLoPerson(p, this); } // produce a list with the given person removed form this list public ILoPerson removePerson(Person p){ throw new RuntimeException("Person with the given name and number " + "is not in our list and cannot be removed"); } } class ConsLoPerson implements ILoPerson{ Person first; ILoPerson rest; ConsLoPerson(Person first, ILoPerson rest){ this.first = first; this.rest = rest; } /* TEMPLATE: ... this.first ... -- Person ... this.rest ... -- ILoPerson ... this.rest.size() ... -- int ... this.rest.contains( Object ) ... -- boolean */ // does this list contain the given person? public boolean contains (Person that){ return this.first.samePerson(that) || this.rest.contains(that); } //EFFECT: // change the phone number for the given person // in this list to the given number public void changePhone(String name, int phone){ if (this.first.name.equals(name)){ this.first.newPhone(phone); } else this.rest.changePhone(name, phone); } // produce a list with the given person added to this list public ILoPerson addPerson(Person p){ return new ConsLoPerson(p, this); } // produce a list with the given person removed form this list public ILoPerson removePerson(Person p){ if (this.first.samePerson(p)){ return this.rest; } else { return new ConsLoPerson(this.first, this.rest.removePerson(p)); } } } // Examples for a list of contacts class Examples{ Examples () {} Person bill = new Person("Bill", 2345); Person matt = new Person("Matt", 1234); Person anne = new Person("Anne", 7896); Person anne1 = new Person("Anne", 7896); Person john = new Person("John", 8866); Person john1 = this.john; Person jane = new Person("Jane", 3456); // reset the value of each person, making a new Person instance for each void resetNewPersons(){ this.bill = new Person("Bill", 2345); this.matt = new Person("Matt", 1234); this.anne = new Person("Anne", 7896); this.anne1 = new Person("Anne", 7896); this.john = new Person("John", 8866); this.john1 = this.john; this.jane = new Person("Jane", 3456); } // reset each person's name and phone number to the original one void resetMutatePersons(){ this.bill.name = "Bill"; this.bill.phone = 2345; this.matt.name = "Name"; this.matt.phone = 1234; this.anne.name = "Anne"; this.anne.phone = 7896; this.anne1.name = "Anne"; this.anne1.phone = 7896; this.john.name = "John"; this.john.phone = 8866; this.john1.name = "John"; this.john1 = this.john; this.jane.name = "Jane"; this.jane.phone = 3456; } // an empty list ILoPerson mtphlist = new MtLoPerson(); // and its wrapper ListPersons lpMtphlist = new ListPersons(this.mtphlist); // a family list ILoPerson family = new ConsLoPerson(this.bill, new ConsLoPerson(this.matt, new ConsLoPerson(this.anne, this.mtphlist))); // and its wrapper ListPersons lpFamily = new ListPersons(this.family); // a friends list ILoPerson friends = new ConsLoPerson(this.anne, new ConsLoPerson(this.john, this.mtphlist)); // and its wrapper ListPersons lpFriends = new ListPersons(this.friends); // reset the ListPersons data to the original values void resetListPersons(){ this.lpMtphlist = new ListPersons(this.mtphlist); this.lpFamily.plist = this.family; this.lpFriends.plist = this.friends; } // We repeat the tests, but now to the ListPersons class // // We then reset all Person data to their original values and verify // that the earlier tests work as they did before. void testChangePhone(Tester t){ // change the phone number for Anne in the family list and test it: this.lpFamily.changePhone("Anne", 4444); t.checkExpect(this.lpFamily.contains(new Person("Anne", 4444)), true); t.checkExpect(this.anne, new Person("Anne", 4444)); // test that an exception is thrown for missing entry t.checkException( new RuntimeException("No person with the given name in our list"), this.lpMtphlist, "changePhone", "Anne", 4444); // verify that the family has the right number for Anne: t.checkExpect(this.family.contains(new Person("Anne", 7896)), false); t.checkExpect(this.family.contains(new Person("Anne", 4444)), true); // and friends know about it too t.checkExpect(this.lpFriends.contains(new Person("Anne", 4444)), true); // we now reset the values of all Person-s to the original ones this.resetMutatePersons(); // and the family has the original number for Anne: t.checkExpect(this.lpFamily.contains(new Person("Anne", 7896)), true); t.checkExpect(this.lpFamily.contains(new Person("Anne", 4444)), false); // and friends know about it too t.checkExpect(this.lpFriends.contains(new Person("Anne", 7896)), true); } // test the methods addPerson for ListPersons void testAdd(Tester t){ // add a person to the empty list this.lpMtphlist.addPerson(this.bill); // now it is no longer an empty list t.checkExpect(this.lpMtphlist.contains(new Person("Bill", 2345)), true); // but our original mtphlist did not change t.checkFail(this.mtphlist.contains(new Person("Bill", 2345)), true); // we add Bill to our list of friends this.lpFriends.addPerson(this.bill); // here the add works OK t.checkExpect(this.lpFriends.contains(new Person("Bill", 2345)), true); // but the the original friends list still does not have Bill in it t.checkExpect(this.friends.contains(new Person("Bill", 2345)), false); // and we reset our data this.resetListPersons(); } // test the methods removePerson for ListPersons void testRemove(Tester t){ // remove a person from the empty list t.checkException( new RuntimeException("Person with the given name and number " + "is not in our list and cannot be removed"), this.lpMtphlist, "removePerson", this.bill); // remove Anne from our list of friends this.lpFriends.removePerson(this.anne); // here the remove works OK t.checkExpect(this.lpFriends.contains(new Person("Anne", 7896)), false); // but the the original friends list still has Anne in it t.checkExpect(this.friends.contains(new Person("Anne", 7896)), true); // and we reset our data this.resetListPersons(); } }