In this program, you are to write 3 different classes that should work together as aggregate classes (has-a relationship) and using inheritance (is-a relationship). It will also use your knowledge of .equals methods, constructors, and deep vs. shallow copies. The classes you should implement are: 1) Point this should be the same Point.java that you have already implemented in MinilabPoint. Points data (x and y values) MUST BE PRIVATE and you are NOT ALLOWED to implement a getX() or a getY() method. Points methods should give you all the functionality you need when writing the Ray class; you should not need to access x and y in any other way. Be sure that Points parameterized constructor, toString, and translate methods work correctly since they will be used to test Ray and StyleRay. You will also need other Point methods to implement methods in the Ray and StyleRay classes. 2) Ray this will implement a Mathematical Ray. It should have the following: Data: That hold an endpoint (as a Point) and a direction (as an int that stores the number of degrees from the x-axis). that hold the x-value and the y-value. This data will be eventually be inherited by a subclass (see below) and should not be public. There are 3 Rays shown below: One Ray has an endpoint of the Point (2, -1) and a direction of 45 (since it is at a 45 angle with the x-axis). Another Ray has an endpoint of the Point (2, -1) and a direction of 225 (since it is a 225 reference angle with the x-axis). It and the first Ray are opposite Rays. The third Ray has an endpoint of the Point (0, 0) and a direction of 135 (since it is a 135 reference angle with the x-axis). Constructors: A default constructor that will initialize the endpoint to a new Point that is (3, 4) and the direction to 135. A parameterized constructor that will receive the endpoint (as a Point) and the direction (as an int). If the Point that is received is null or if the direction is not between 0 and 359 (including both), then throw new IllegalArgumentException(); If the direction is OK, then initialize the data to what is received. Be sure a deep copy is used in this case. A copy constructor that will receive another Ray. If the Ray that is received is null, then throw new IllegalArgumentException(); If the Ray that is received is OK, then it should initialize its data to be the same as the Ray that was received. Be sure a deep copy is used. Methods: A toString() method that returns a String representing the Ray. It should be in the form endpoint----->direction Example: (3, 4)----->135 It is using the endpoint, 5 dashes, a >, and the direction. Be exact. A method called translate(int xmove, int ymove) that will return nothing and translates, or shifts, itself by the distances passed in. A method called rotate(int angle), which will receive an angle and return nothing. If the angle received is negative, it should: throw new IllegalArgumentException(); If the angle is OK, then it should change the direction by adding the angle to it. Butif that makes the direction be >= 360, then the method should change it to be from 0-359. For example: If (3, 4)----->135 is told to rotate(800) then its direction will change to 935. But that is actually twice around the circle and ending up at 215. So it should be corrected to finally be: (3, 4)----->215 A method called equals(Object obj), which receives an Object and returns true if its endpoint and its direction are both equal to the endpoint and direction of the Object (Ray) that was received. It should be implemented like we did in class. A method called isOpposite(Ray another), which receives another Ray and returns true of the instance and the Ray that is received are opposites. Two Rays are defined as opposites if they have the same endpoint but go in opposite directions (like the Rays shown in the example above). If the Ray that is received is null, then throw new IllegalArgumentException(); A method called aboveXAxis(), which returns a boolean that will be true if any part of the Ray extends to above the x-axis. 3) StyleRay this will be a subclass of Ray and could also be either dashed, dotted, or double. Data: Its endpoint (as a Point) and direction (as an int) will be inherited from the parent class. In addition, StyleRay should also have a String which holds the style (either dashed, dotted, or double). Constructors: Since constructors are not inherited, you will have to implement these constructors. In some cases they work very similarly to the parent classs constructors. If you want, you could call the parents constructor, using super(); A default constructor that will initialize the endpoint to a new Point that is (3, 4) and the direction to 135 (same as its parent class). In addition, it will initialize its style to double. A parameterized constructor that will receive the endpoint (as a Point) and the direction (as an int) and the style (as a String). If the Point that is received or the String that is received are null, then throw new IllegalArgumentException(); If the direction is not between 0 and 359 (inclusive), then throw new IllegalArgumentException(); Also, if the style that is received is not equal to double or dashed or dotted then throw new IllegalArgumentException(); If the direction and style are OK, then initialize the data to the Point, int, and String that are received. Be sure deep copies are used in this case. A copy constructor that will receive another StyleRay. If the Ray that is received is null, then throw new IllegalArgumentException(); It should initialize its data to be the same as the StyleRay that was received. Be sure deep copies are used. Methods: Almost every StyleRay method can be inherited from its parent class except for the following: A toString() method which will receive nothing and return a String representing the StyleRay. Depending on the type, the String representation will look like this: If the style equals double it should be endpoint=====>direction Example: (3, 4)=====>135 It is using the endpoint, 5 equal signs, a >, and the direction. Be exact. If the style equals dotted it should be endpoint..>direction Example: (3, 4)..>135 It is using the endpoint, 5 periods, a >, and the direction. Be exact. If the style equals dashed it should be endpoint- >direction Example: (3, 4)- - ->135 It is using the endpoint, 3 dashes with a space between each, a >, and the direction. Be exact. If the style is anything but the above Strings, something is wrong. It should not happen, (so I cannot create a test case for it) but you can use a last else in your logic and: throw new IllegalStateException(); A method called equals(Object obj), which receives an Object and returns true if its endpoint and its direction are both equal to the endpoint and direction of the Object (as a StyleRay) that was received. NOTE that it does not check to see if the styles are the same. Because of this, it could just be inherited, but I would like it to be specifically implemented like we did in class. A method called isOpposite(Ray another), Like others, this method can just be inherited from the parent class without any changes. Note that this inherited method will still be defined to receive a Ray. So it will also be able to receive a StyleRay (a StyleRay is also a Ray since it is a subclass). Therefore, a Ray and a StyleRay can be opposites. Comments and formatting: Please put in an opening comment that briefly describes the purpose of your program. Each constructor/method should have a brief descriptive comment. If any of the code is tricky, help out the reader by putting in a brief comment explaining it. Also, please be sure that your indenting is correct and that your variable names are meaningful. This is important for maintainability; deductions for lack of comments and formatting could be as high as 10% of the program. Submitting your program: Please use HyperGrade to submit and test your program (the Point, Ray, and StyleRay classes). It is a very good skill to be able to think up and write test cases yourself, too