Description
This Assignment involves developing increasingly general (eventually using Java Generics) Generators that implement the Iterable and Iterator interfaces within the Java API. Rather than iterating through a pre-existing collection of data, your code will be generating this data on demand. The final generalization of this pattern will be used to explore the structure of Wikipedia and the significance of its Philosophy page.
OBJECTIVES AND GRADING CRITERIA
The main goals of this assignment include giving you practice and experience with both Generics and Iterators in Java. You will implement the Iterable and Iterator interfaces of the Java API, and practice generalizing your code to be useful in a wider variety of applications.
20 points
4 zyBooks Tests: automated grading test results are visible upon submission, and allow multiple opportunities to correct the organization and functionality of your code. Your highest scoring submission prior to the deadline will be recorded.
10 points
2 Hidden Tests: automated grading tests are run after the assignment’s deadline. They check for similar functionality and organizational correctness as the zyBooks Tests. But you will NOT be able to resubmit corrections for extra points, and should therefore consider and test your own code even more thoroughly
20 Final Submission Commenting, Style and Organization: human graders will review the
LECTURE NOTES
points commenting, style, and organization of your final submission. They will be looking for clear comments and consistent style that make appropriate use of java constructs, conforms to this write-up and the CS300 Course Style Guide, while contributing to the readability of your code.
GETTING STARTED
0. Create a new Java8 project in Eclipse. You can name this project whatever you like, but Generating Philosophy is a descriptive choice. Then create a new class named Main with a public static void main(String[] args) method stub.
EVEN NUMBER GENERATOR
1. Create an new class named EvenNumberGenerator that implements both Iterable and Iterator. The signature of the constructor for this class should match the following, and the behavior of the methods that must be defined in this class are also described in these comments:
Implement this constructor along with each of the required methods associated with the interfaces implemented by this class: hasNext(), next(), and iterator(). Note that although it is common to separate the functionality of Iterator and Iterable into separate classes, we can make our Iterator EvenNumberGenerator Iterable by having it return a reference to itself from its iterator() method. 2. From the main method of your Main class, instantiate and test and instance of your EvenNumberGenerator class. You should test it both by calling it’s methods directly, and by using it within a for-each loop. For example, one such test might include the following code which prints out: 12 14 16 18 20
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/** * Initializes a new EvenNumberGenerator to return a single even number * each time it’s next() method is called. The first even number returned * in this way is firstEven. Subsequent even numbers returned in this way * will be the smallest even number that is larger than the previous. *
* After numberOfEvens numbers have been generated and returned from this * next() method, the generator will end: its hasNext() method will return * false, and its next() method will throw a NoSuchElementException when * called after this point. * * @param numberOfEvens – the number of evens that can be generated * @param firstEven – the first and smallest even that will be generated * @throws IllegalArgumentException – when numberOfEvens is negative, or * when firstEven is not an even number */ public public EvenNumberGenerator(int int numberOfEvens, Integer Integer firstEven) throws IllegalArgumentExce // TODO : implement this constructor }
NUMBER GENERATOR
3. Since generating sequences of even numbers may be of limited use, we’ll next create a more general NumberGenerator class. By copy+pasting the EvenNumberGenerator class within the “Project Explorer” in Eclipse, you can give this copy the new class name NumberGenerator, and maintain a copy of the code from your previous class to start working from. 4. The part of this class that we’d like to generalize is the part of the next() method that adds two to the previous even number, to compute the smallest even number that is larger than the last. Instead of only adding two, we’d like each NumberGenerator object to be able to perform an arbitrary computation to calculate the next number, based on the previous. We’ll use the Function<T,R> interface from the JavaAPI to store and make use of this arbitrary computation within an object. Notice that implementing this interface requires a single method definition, and that this method will determine how we calculate the next number that we generate based on the previous one:
Add a third parameter to your NumberGenerator constructor that has the type Function<Integer,Integer>, and then store the value passed into this constructor within a private instance field. Instead of adding two to your previous even number to compute the next, you’ll compute the next by calling this apply method. The input to this method is your previous number, and the return value will be the next. While updating your NumberGenerator class, you should also remove the restriction of only allowing an even starting value from the constructor. 5. To test and make use of your NumberGenerator class, you’ll want to define some classes that implement the Function<Integer,Integer> interface. To do this, let’s define a class called DoubleFunction which implements the Function<Integer,Integer> interface in our Main.java source file (remember that we must leave off the public access modifier when defining a class in a file with a different name). The apply method in this class should return a value that is double or two times the input. With this implementation, the following code should print out: 2 4 8 16 32
GENERATOR
6. Let’s further generalize our NumberGenerator class by creating a copy of that class named Generator (use Eclipse’s copy+paste tool again, like we did in step 3). The generalization that we’d like to implement is to make this new Generator class work with any type of object, instead of only working with Integer objects. We’ll accomplish this by making use of a Generic class parameter.
1 2
for for(int int i : new new EvenNumberGenerator(5, 12)) System.out.print(i + ” “);
1 public public R apply(T t);
1 2
for for(int int i : new new NumberGenerator(5, 2, new new DoubleFunction())) System.out.print(i + ” “);
7. To test this Generator class, let’s create an AddExclamationFunction class that implements the Function<String,String> interface. We’ll once again include this class definition within Main.java (since it is such a simple class). The apply method in this class should return the input string with one extra exclamation mark appended to the end. The following is one test that you can run using these new classes (Generator and AddExclamationFunction), which should result in displaying: Hello Hello! Hello!! Hello!!!
PHILOSOPHY
8. Now that we have developed a general Generator class, let’s make use of that Generator to implement one more application. An interesting observation was made several years back, that the following process will lead you to the Wikipedia page for Philosophy, when followed from as many as 97% or random starting Wikipedia pages. 1) Choose a random starting Wikipedia page, 2) follow the first link within this page’s description text (excluding pronunciation and citation links), and then 3) repeat step 2 until the page for Philosophy has been reached. Here’s a short video about this observation: https://www.youtube.com/watch?v=Q2DdmEBXTpo 9. We could view this process of following Wikipedia links from one page to the next as a Generator. In fact we can use our Generator to implement this, if we first define an appropriate implementation of the Function interface. Here is the code for such a class (put this code in it’s own source file) that utilizes the jsoup library, you can download the .jar file here.
1 2
for for(String String i : new new Generator(4, “Hello”, new new AddExclamationFunction())) System.out.print(i + ” “);
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
import java.io.IOException; import java.util.function function.Function Function; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.select.Elements; public public class class NextWikiLinkFunction implements implements Function Function { @Override public public String String apply(String String t) { try try { // Download a Wikipedia page, using t in their internal link format: /wiki/Some Document doc = Jsoup.connect(“https://en.wikipedia.org” + t).get(); // Use .css selector to retrieve a collection of links from this page’s descrip // “p a” selects links within paragraphs // “:not(span a)” skips pronunciations // “:not(sup a)” skips citations Elements links = doc.select(“p a:not(span a):not(sup a)”); // return the link attribute from the first element of this list return return links.get(0).attr(“href”); // Otherwise return an appropriate error message: } catch catch(IOException|IllegalArgumentException e) { return return “FAILED to find wikipedia page: ” + t; } catch catch(IndexOutOfBoundsException e) { return return “FAILED to find a link in wikipedia page: ” + t; } } }
10. Your last job for this assignment is to make use of the provided NextWikiLinkFunction with your Generator class. Remove any previous tests from the main() method within your class Main, and replace them with the following. Implement a console based interface that prompts the user to enter the name of a potential Wikipedia page. Based this this starting page, your code should generate a maximum of 100 Wikipedia page links by repeatedly following the first link within each pages description (using the provided NextWikiLinkFunction class). After reaching the link to the page /wiki/Philosophy, or retrieving either of the error links (that start with “FAILED “) your program should stop. All of the links up to this point should be displayed in a numbered list by your program. Two last implementation details to be aware of: there are no spaces in any of these Wikipedia links, and that they all start with “/wiki/”. If the user enters spaces, you should convert those spaces into underscores for them. You should also prepend “/wiki/” in front of the user’s input before passing it into a new Generator. Here are two sample logs that demonstrate using this complete application (the user’s input is displayed in a bold orange font): Please enter a Wikipedia topic: american english 0: /wiki/american_english 1: /wiki/Language_variety 2: /wiki/Sociolinguistics 3: /wiki/Society 4: /wiki/Social_group 5: /wiki/Social_science 6: /wiki/Discipline_(academia) 7: /wiki/Knowledge 8: /wiki/Fact 9: /wiki/Verificationism 10: /wiki/Philosophy
Please enter a Wikipedia topic: this does not exist 0: /wiki/this_does_not_exist 1: FAILED to find wikipedia page: /wiki/this_does_not_exist
11. Congratulations on finishing this CS300 assignment! After verifying that your work is correct, and written clearly in a style that is consistent with the course style guide, you should submit your work through zybooks. The most recent of your highest scoring submissions prior to the deadline of 17:00 on Thursday, November 2nd will be used as part of your score for this assignment. Additional grading tests will then be run against your highest scoring submission, and human graders will also review the commenting, style, and clarity of this code to determine the rest of your assignment grade.