In the class we extensively discussed a generic singly linked list implemented as a node class. Implement a generic node class called DoublyNode in which each node contains an element of type E and each node is linked not only forward to the next element in the list but also backward to the previous element in the list. Your implementation should adapt and implement all the methods of generic Node including the following methods: Constructor for DoublyNode addNodeAfter, removeNodeAfter getData, setData getForeLink, setForeLink getBackLink, setBackLink listCopy listCopyWithTail listLength listPart listPosition listSearch Solution import java.util.ListIterator; import java.util.NoSuchElementException; import java.util.Random; public class DoublyNode { private Node head; private Node tail; private int size; public DoublyNode() { size = 0; } private class Node { E element; Node getForeNode; Node getBackNode; public Node(E element, Node next, Node prev) { this.element = element; this.getForeNode = next; this.getBackNode = prev; } } public int listLength() { return size; } public boolean isEmpty() { return size == 0; } public void addFirst(E element) { Node tmp = new Node(element, head, null); if(head != null ) {head.getBackNode = tmp;} head = tmp; if(tail == null) { tail = tmp;} size++; System.out.println(\"adding: \"+element); } public void addNodeAfter(E element) { Node tmp = new Node(element, null, tail); if(tail != null) {tail.getForeNode = tmp;} tail = tmp; if(head == null) { head = tmp;} size++; System.out.println(\"adding: \"+element); } public void addNodeAfterSpecifiedNode(E element, E tobeAddedAfter) { Node prevTobeAddedAfter = listSearch(element); Node afterNode = prevTobeAddedAfter.getForeNode; Node tmpNode = new Node(element,prevTobeAddedAfter,afterNode); tmpNode = prevTobeAddedAfter.getForeNode; afterNode = tmpNode.getForeNode; } public void listCopy(){ System.out.println(\"iterating forward..\"); Node tmp = head; while(tmp != null){ System.out.println(tmp.element); tmp = tmp.getForeNode; } } public Node listSearch(E item){ System.out.println(\"Searching Item \"+item); Node tmp = head; while(tmp != null){ System.out.println(tmp.element); if(tmp.element == item) { System.out.println(\"Item found \"+item); return tmp; } tmp = tmp.getForeNode; } return null; } public void iterateBackward(){ System.out.println(\"iterating backword..\"); Node tmp = tail; while(tmp != null){ System.out.println(tmp.element); tmp = tmp.getBackNode; } } public E removeFirst() { if (size == 0) throw new NoSuchElementException(); Node tmp = head; head = head.getForeNode; head.getBackNode = null; size--; System.out.println(\"deleted: \"+tmp.element); return tmp.element; } public E removeNodeAfter() { if (size == 0) throw new NoSuchElementException(); Node tmp = tail; tail = tail.getBackNode; tail.getForeNode = null; size--; System.out.println(\"deleted: \"+tmp.element); return tmp.element; } }.