CSE 331, Spring 2011, Final Exam Key There are many possible answers to any problem. These constitute one possible set of answers that would receive full credit. Q1. Java Object Methods // Invariants: courses != null, name != null, 1 <= year <= 4, 0.0 <= gpa <= 4.0 public class Student implements Cloneable, Comparable, Serializable { private List courses; private String name; private int year; private double gpa; // your code goes here public Student clone() { try { Student copy = (Student) super.clone(); copy.courses = new ArrayList(); for (Course course : courses) { copy.courses.add(course.clone()); } return copy; } catch (CloneNotSupportedException cnse) { return null; } } public int compareTo(Student other) { if (other == null) { throw new IllegalArgumentException(); } if (year != other.year) { return year - other.year; } else if (courses.size() != other.courses.size()) { return courses.size() - other.courses.size(); } else { return name.compareTo(other.name); } } public boolean equals(Object other) { if (other != null && this.getClass() == other.getClass()) { Student student = (Student) other; return courses.equals(student.courses) && name.equals(student.name) && year == student.year && gpa == student.gpa; } else { return false; } } public int hashCode() { return 12345 * courses.hashCode() + 4731 * name.hashCode() + 37 * year + new Double(gpa).hashCode(); } } Q2. Specs and Comments /** * Replaces any occurrences in the given list of the given 'from' string * with the given 'to' string. Can use exact matches or case-insensitive * matches. Returns the number of strings that were replaced. * * @pre no element of the list is null * @post all occurrences of 'from' in 'list' will be changed to 'to' * @post if !from.equals(to), then !list.contains(from) * @modifies list (if the list contains 'from' and !from.equals(to)) * * @param list the list of strings to examine; should not be null * @param from the original string value to be replaced; should not be null * @param to the new string value to replace 'from' with; can be null * @param caseSensitive whether to allow mixed-case matches; if true, any * string that matches 'from' case insensitively will be replaced * @return the number of replaced strings (0 if no strings were replaced) * @throws IllegalArgumentException if list or 'from' is null */ Q3. JUnit Testing public class ReplaceAllTest { @Test(timeout=2000) public void testReplaceAll_validCaseSensitive() { helper(Arrays.asList("a", "b", "c", "B", "b", "d"), "b", "x", true, Arrays.asList("a", "x", "c", "B", "x", "d"), 2); } @Test(timeout=2000) public void testReplaceAll_validCaseInsensitive() { helper(Arrays.asList("al", "bob", "carl", "Bob", "BOB", "d", "bOb"), "bob", null, false, Arrays.asList("al", null, "carl", null, null, "d", null), 4); } @Test(timeout=2000) public void testReplaceAll_validEmpty() { helper(new ArrayList(), "", null, false, new ArrayList(), 0); } @Test(timeout=2000, expected=IllegalArgumentException.class) public void testReplaceAll_invalidNullList() { helper(null, "bob", "alice", true, null, 0); } @Test(timeout=2000, expected=IllegalArgumentException.class) public void testReplaceAll_invalidNullFrom() { helper(Arrays.asList("a", "b"), null, "alice", true, Arrays.asList("a", "b"), 0); } private void helper(List list, String from, String to, boolean caseSensitive, List expected, int expectedReturn) { int result = replaceAll(list, from, to, caseSensitive); assertEquals("list contents", expected, list); assertEquals("return value", expectedReturn, result); } } Q4. Object-Oriented Design * Model/Application/IMProgram o description: represents the overall app model o fields: users o methods: addObserver * User o fields: accounts o methods: login, logout * Account o fields: name, email, password, avatar, status o methods: block/unblock(person), changePassword, delete o possible Status enum: AVAILABLE, AWAY, IDLE, ... * BuddyList o fields: buddies, groups o methods: add, remove, sort, contains, size o possible class: Buddy/Friend * Conversation o fields: person, messages, log o methods: addObserver, getMessages o possible class: History / Log * Message o fields: from, to, text o methods: send, receive Q5: Design Patterns (a) Composite (b) Flyweight (c) State (d) Observer (e) Factory ("Factory Method" or "Abstract Factory" okay) (f) Decorator (g) Adapter Q6: Graphical User Interfaces public LayoutGui() { // your code begins here JPanel south = new JPanel(new GridLayout(1, 3)); south.add(a); south.add(b); south.add(c); JPanel north = new JPanel(new FlowLayout()); north.add(fromField); north.add(replace); north.add(toField); JPanel center = new JPanel(new BorderLayout()); center.add(north, BorderLayout.NORTH); center.add(listLabel, BorderLayout.CENTER); center.add(sensitive, BorderLayout.SOUTH); frame.add(hello, BorderLayout.WEST); frame.add(south, BorderLayout.SOUTH); frame.add(center, BorderLayout.CENTER); // events replace.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent event) { replaceAll(list, fromField.getText(), toField.getText(), sensitive.isSelected()); listLabel.setText(list.toString()); } }); listLabel.setText(list.toString()); frame.setTitle("Lay it out"); frame.pack(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); }