We would like to build a generic list in such a way that we can start either at the front, or at the back, and move through the list in either direction. Here is an example of such a list (shown here with Strings), drawn as an object diagram: Every Deque has a header that consists of the Sentine L node. Ihis header neld does not change, but the fields within the Sentinel node (that provide the links to the first and the last item in the Deque) can and will change. Each data Node has two links, one to the next item in the list and one to the previous item in the list. The Sentinel node is always present. It also has next and prev fields, which are consistently updated to link to the head of the list and to the tail of the list, respectively. The Sentinel and Node classes both inherit from a common superclass (shown below), because the next or prev item after any given node may be either a data-carrying Node or the Sentinel marking the end of the list. The list shown above has four data-carrying nodes and the lone sentinel. The empty list has just the Sentinel, and its links to the first and to the last item just reference the Sentinel node itself. So an empty list would have the following object diagram: The list shown above has four data-carrying nodes and the lone sentinel. The empty list has just the Sentinel, and its links to the first and to the last item just reference the Sentinel node itself. So an empty list would have the following object diagram: The class diagram for these classes is as follows: We have an abstract class ANode T, which can be either a Sentinel T> node or an actual Node T containing data. We use an abstract class here instead of an interface because we need to share the next and prev fields. Moreover, because all ANodes are contained and hidden within the Deque, no external code needs to know about it: they are implementation details rather than a publicly visibly datatype definition. 8.1 Data definitions and examples - Define the classes ANode T, Node T, Sentinel T, and Deque T. - For Sentinel, define a constructor that takes zero arguments, and initializes the next and prev fields of the Sentinel to the Sentinel itself. - For Node T, define two constructors: the first one takes just a value of type T, initializes the data field. The next and prev fields would be nutl. The second convenience constructor should take a value of type T and two ANode nodes, initialize the data field to the given value, initialize the next and prev fields to the given nodes, and also update the given nodes to refer back to this node. Throw an IllegalArgumentException in this constructor if either of the given nodes is null. (You can use if (theNode == null) {} to test for null-ness.) Note carefully the order of the arguments in this constructor! The order should match the class diagram above; getting the order wrong will result in oddly "backwards" lists. - For Deque T, define two constructors: one which takes zero arguments and initial.