Lab:
Social Media

Beware! MapMonster is here for your code!

In this lab, you will be using sets and maps to make a fake social media application. You will also be implementing the Set and Map interfaces.


Files

Download and unzip socialmedialab.zip, which contains a number of files.

Classes you will complete:

Files provided for you to use:

Files you can ignore: DrawPanel.java, PostDialog.java, and PostPanel.java.


Reference

interface java.util.Set<E>

int size()

boolean contains(Object obj)

boolean add(E obj)

if obj is not present in this set, adds obj and returns true; otherwise returns false

boolean remove(Object obj)

if obj is present in this set, removes obj and returns true; otherwise returns false


interface java.util.Map<K,V>

int size()


V get(Object key)

returns the value associated with key, or null if there is no associated value

V put(K key, V value)

associates key with value; returns the value formerly associated with key, or null if key was not present

V remove(Object key)

removes and returns the value associated with key; returns null if there is no associated value

Set<K> keySet()

  returns a set of the keys in the map; because the returned set is still connected to the map, removing a key from the set will remove that key/value pair from the map, and adding a key to the set is forbidden


class java.util.TreeSet<E> implements java.util.Set<E>
class java.util.TreeMap<K,V> implements java.util.Map<K,V>

Part 0: Post (0 points)

The Post class has been provided to you. It represents a user's post on our social media application. Each Post has a text message and a drawing consisting of zero or more lines. Go ahead and familiarize yourself with the Post class constructor and methods below. Then move on to Part 1.

Post(String name, long time) // constructs an empty Post for given user name and time

String getName()             // returns name of user who posted this

long getTime()               // returns the time this was posted

String getText()             // returns posted text message

Set<Line> getDrawing()       // returns posted line drawing

void setText(String text)    // replaces posted text message

void addLine(Line line)      // adds Line to posted line drawing

Part 1:  User (20 points)

The User class represents one user on our social media application. Each User has a collection of posts and the names of other users they follow. The User class's constructor and methods are illustrated by the following code segment.

User aluser = new User("Al");


aluser.follow("Bo");

aluser.follow("Cy");

boolean b;

b = aluser.isFollowing("Bo");  // true

b = aluser.isFollowing("Cy");  // true


aluser.unfollow("Cy");

b = aluser.isFollowing("Bo");  // true

b = aluser.isFollowing("Cy");  // false


Post post1 = some Post object;

long time1 = post1.getTime();  // 946702800000, for example

aluser.addPost(post1);

aluser.setPostText(time1, "I dyed my hair blonde!!! (and I guess I'm having twins)");

// replaced text in post1 (precondition: Post with given time has already been added to User)


Post post2 = another Post object;

long time2 = post2.getTime();  // 1332977400000, for example

aluser.addPost(post2);

aluser.setPostText(time2, "Let’s set a world record together with this world_record_triangle!");

// replaced text in post2

aluser.addLineToPost(time2, new Line(0, 100, 100, 100));

aluser.addLineToPost(time2, new Line(0, 100, 50, 0));

aluser.addLineToPost(time2, new Line(50, 0, 100, 100));

// added 3 lines to post2 (precondition: Post with given time has already been added to User)


Set<Post> posts = aluser.getPosts();  // returns set containing post1 and post2


Open User.java. The User class has three fields: the user's name, the Set of user names they are following, and a Map containing the user's posts. The keys of the Map are unique integer identifiers, and the values are the Posts themselves.

private String name;
private Set<String> following;
private Map<Long,Post> posts;

Do not add any other fields to this class.

The unique integer identifiers used as keys in the Map actually represent the system time when the Post was constructed. The system time is just the number of milliseconds elapsed since January 1, 1970. Because this is a really big number, it is represented using a long instead of an int. Roughly speaking, a long can store twice as many digits as an int. Remember that whenever we want to store an int in an ArrayList, ListNode, etc., we use Java's Integer wrapper class. Likewise, to store a long in our Map, we use Java's Long wrapper class.

For example, after running the code segment above, the posts field contains the following data.

Key              Value

946702800000  Post object with time 946702800000 and text "I dyed ..."

1332977400000    Post object with time 1332977400000 and text "Let’s set  ..."


Exercise 1-1: User

Complete the User class definition so that it behaves as shown above. Remember that you cannot construct a Set, because Set is an interface. Java's mysterious TreeSet class correctly implements the Set interface, so you should construct a TreeSet whenever you need to create an empty Set. Likewise, Java's TreeMap class correctly implements the Map interface.


Exercise 1-2: Main

Open Main.java, which contains a single method, also called main. This method creates a window for viewing the social media application.

Compile Main.java and run the Main class's main method. You should see a window pop up. In the title bar, it tells you that you are "Logged in as Bort".

If your name is not Bort, choose a more appropriate user name. (Note that you cannot have any spaces in your user name.) Modify the main method to use this new user name. If your name is Bort, then do not modify the main method!

Run the main method and confirm that your new user name now appears in the title bar.

Of course, nothing else works in this window, because you're not done with the lab yet ...

Part 2: Directory (25 points)

The Directory class stores all users of our social media application. Specifically, it has a single field called userMap of type Map, whose keys are user names and whose values are the corresponding User objects.

private Map<String,User> userMap;

For example, if our Directory contains 3 users named Al, Bo, and Cy, then userMap will appear as follows.

Key      Value

"Al"     User object with name "Al"

"Bo"     User object with name "Bo"

"Cy"     User object with name "Cy"

Do not add any other fields to this class.

The Directory class's constructor and methods are empty. It will be your job to fill in that code in the following exercises.


Exercise 2-1: Names

Consider the following code segment.

Directory dir = new Directory();

dir.addUserIfNew("Al");

dir.addUserIfNew("Bo");

dir.addUserIfNew("Cy");

dir.addUserIfNew("Di");

dir.addUserIfNew("Bo");  // ignored, because "Bo" has already been added

Set<String> names = dir.getNames("Cy"); // returns {Al, Bo, Di} -- all names except for given string

Complete the Directory class's constructor, addUserIfNew method, and getNames method, so that they behave as shown above.

Test your code by running the Main class's main method. You should now see a list of names in the Follow box on the left side of the window. This is a list of the other social media users saved in the data.txt file. Your own user name should not appear in the list. (In other words, the Display class uses the getNames method you just wrote to get the names of all users other than the one that's currently logged in.)

Try changing the main method to use one of the names you do see, and confirm that this name no longer appears in the Follow list.


Exercise 2-2: Following

Consider the following code segment.

dir.follow("Al", "Bo");          // Al will now follow Bo's posts


boolean b;

b = dir.isFollowing("Al", "Bo"); // returns true (Al is following Bo's posts)

b = dir.isFollowing("Bo", "Al"); // returns false (Bo is not following Al's posts)


dir.follow("Cy", "Al");          // Cy will now follow Al's posts

b = dir.isFollowing("Cy", "Al");  // returns true (Cy is following Al's posts)


dir.unfollow("Cy", "Al");        // Cy will not follow Al's posts's anymore

b = dir.isFollowing("Cy", "Al");  // returns false (Cy is not following Al's posts)

Complete the Directory class's follow, unfollow, and isFollowing methods, so that they behave as shown above.

(You will not see the effects of these changes in the Display yet.)


Exercise 2-3: Feed

Consider the following code segment.

dir.addPost(new Post("Al"));

dir.addPost(new Post("Bo"));

dir.addPost(new Post("Cy"));

dir.addPost(new Post("Al"));

Set<Post> feed;

feed = dir.getFeed("Al"); // returns both of Al's posts

dir.follow("Al", "Bo");

feed = dir.getFeed("Al"); // returns both of Al's posts AND Bo's post

As shown above, the Directory class's addPost method adds the given post to the appropriate User. The getFeed method returns a set that includes (1) all posts made by the user with the given name, and (2) all posts made by any user followed by the user with the given name. Complete the addPost and getFeed methods.

Test your code by running the main method. Click on the New Post button. In the dialog that pops up, write a message in the text field at the top and/or draw a picture in the large square region. Each new post you create should now appear at the top of the Feed box on the right side of the main window. You will not be able to see the content of posts from other users yet.


Exercise 2-4: setPostText

Complete the setPostText method, which replaces the text message associated with an existing post. The method takes in the name of the user who made the post, the time the post was created, and the new text message. The method finds the existing Post matching that name and time, and replaces its text message with the given text.

Test your code by running the main method. Click on a user name to follow them, and you should now see any text messages they posted. Try following and unfollowing, as well as creating your own posts.


Exercise 2-5: addLineToPost

Complete the addLineToPost method, which adds a Line to an existing post. The method takes in the name of the user who made the post, the time the post was created, and a Line. The method finds the existing Post matching that name and time, and adds the given Line to its drawing.

Test your code by running the main method. You should now see drawings posted by the users you are following.

Part 3:  SimpleSet (20 points)

Open SimpleSet.java. A SimpleSet implements the Set methods shown above by storing its elements in an ArrayList. Complete these methods so that they behave exactly as specified above.

Be sure to test your code.

Part 4:  SimpleMap (25 points)

Open Entry.java, which defines the Entry<K,V> class. The following code segment makes use of the Entry class.

Entry<Integer,Boolean> e = new Entry<Integer,Boolean>(2, true);
System.out.println(e.getKey());
System.out.println(e.getValue());
e.setValue(false);
System.out.println(e.getKey());
System.out.println(e.getValue());

What do you think it will print? Run the code to test your prediction.

Now open SimpleMap.java. A SimpleMap implements the Map methods shown above by storing its data in an ArrayList of Entry objects. For example, the following map data

Key  Value
A    6
B    1
C    4

is stored inside SimpleMap as:

Complete the given methods. These methods should behave exactly as specified above. Note that the keySet method will return a SimpleSet.

Be sure to test your code.

Part 5: Saving (5 points)

In this part, we'll modify our social media application so that it saves all posts, along with who is following whom. Consider the following code segment.

Directory dir = new Directory();

dir.addUserifNew("Lee");

dir.addUserifNew("Roy");

dir.addUserIfNew("Sam");

dir.follow("Roy", "Lee");

dir.follow("Roy", "Sam");

dir.unfollow("Roy", "Sam");

dir.follow("Roy", "Sam");

Post p = new Post("Lee");

p.setText("Here's my favorite letter");

p.addLine(new Line(20, 10, 20, 90));

p.addLine(new Line(20, 90, 80, 90));

dir.addPost(p);

List<String> toSave = dir.save();

After the above code segment executes, toSave contains the following 5 strings (which will later be written to a text file).

follow Roy Lee

follow Roy Sam

text Lee 1153700000000 Here's my favorite letter

line Lee 1153700000000 20 10 20 90

line Lee 1153700000000 20 90 80 90

In the List returned by save in this example:

Complete the Directory class's save method so that it behaves as described. Your code must save ALL of the following/post information--not just recently changed info. The strings in your list may appear in any order, with one exception. The text of a post must always appear somewhere before any lines from that same post. You may write additional methods, but you cannot add any new fields.

When you're ready to test your code, open Main.java. In the main method, you will see the following code.

new Display("Bort", "data.txt", false);

This code runs our social media application.

When you're ready, try changing the third argument to true, to tell the Display to save to the text file, but make a copy of the text file before trying this! If your code works, you should be able to check/uncheck boxes, make new posts, exit the social media application, restart the application, and still see the changes you made.

If you need to, you can redownload data.txt here.

Additional Credit Suggestions