package position; import exceptions.*; import iterator.ElementIterator; import position.utility.DNode; import java.util.Iterator; import java.util.NoSuchElementException; /** * Realization of a PositionList using a doubly-linked list of nodes. * * @author Michael Goodrich, Natasha Gelfand, Roberto Tamassia, Eric Zamore */ //Copyright (c) 2003 Brown University, Providence, RI //Additional modifications and methods by xgiovio public class NodePositionList implements PositionList { protected int numElts; // Number of elements in the list protected DNode header, trailer; // Special sentinels public NodePositionList() { numElts = 0; header = new DNode(null, null, null); // create header trailer = new DNode(header, null, null); // create trailer header.setNext(trailer); // make header and trailer point to each other } protected DNode checkPosition(Position p) throws InvalidPositionException { if (p == null) throw new InvalidPositionException ("Null position passed to NodeList"); if (p == header) throw new InvalidPositionException ("The header node is not a valid position"); if (p == trailer) throw new InvalidPositionException ("The trailer node is not a valid position"); try { DNode temp = (DNode) p; if ((temp.getPrev() == null) || (temp.getNext() == null)) throw new InvalidPositionException ("Position does not belong to a valid NodeList"); return temp; } catch (ClassCastException e) { throw new InvalidPositionException ("Position is of wrong type for this list"); } } public int size() { return numElts; } public boolean isEmpty() { return (numElts == 0); } public Position first() throws EmptyListException { if (isEmpty()) throw new EmptyListException("List is empty"); return header.getNext(); } public Position last() throws EmptyListException { if (isEmpty()) throw new EmptyListException("List is empty"); return trailer.getPrev(); } public Position prev(Position p) throws InvalidPositionException, BoundaryViolationException { DNode v = checkPosition(p); DNode prev = v.getPrev(); if (prev == header) throw new BoundaryViolationException ("Cannot advance past the beginning of the list"); return prev; } public Position next(Position p) throws InvalidPositionException, BoundaryViolationException { DNode v = checkPosition(p); DNode next = v.getNext(); if (next == trailer) throw new BoundaryViolationException ("Cannot advance past the end of the list"); return next; } public Position addBefore(Position p, E element) throws InvalidPositionException { DNode v = checkPosition(p); numElts++; DNode newNode = new DNode(v.getPrev(), v, element); v.getPrev().setNext(newNode); v.setPrev(newNode); return newNode; } public Position addAfter(Position p, E element) throws InvalidPositionException { DNode v = checkPosition(p); numElts++; DNode newNode = new DNode(v, v.getNext(), element); v.getNext().setPrev(newNode); v.setNext(newNode); return newNode; } public void addFirst(E element) { numElts++; DNode newNode = new DNode(header, header.getNext(), element); header.getNext().setPrev(newNode); header.setNext(newNode); } public void addLast(E element) { numElts++; DNode oldLast = trailer.getPrev(); DNode newNode = new DNode(oldLast, trailer, element); oldLast.setNext(newNode); trailer.setPrev(newNode); } public E remove(Position p) throws InvalidPositionException { DNode v = checkPosition(p); numElts--; DNode vPrev = v.getPrev(); DNode vNext = v.getNext(); vPrev.setNext(vNext); vNext.setPrev(vPrev); E vElem = v.element(); v.setNext(null); v.setPrev(null); return vElem; } public E set(Position p, E element) throws InvalidPositionException { DNode v = checkPosition(p); E oldElt = v.element(); v.setElement(element); return oldElt; } public boolean isFirst(Position p) throws InvalidPositionException { DNode v = checkPosition(p); return v.getPrev() == header; } public boolean isLast(Position p) throws InvalidPositionException { DNode v = checkPosition(p); return v.getNext() == trailer; } public void swapElements(Position a, Position b) throws InvalidPositionException { DNode pA = checkPosition(a); DNode pB = checkPosition(b); E temp = pA.element(); pA.setElement(pB.element()); pB.setElement(temp); } @Override public String toString() { String to_return = ""; to_return = to_return + "["; for ( DNode temp = header.getNext(); temp != trailer ; temp = temp.getNext()){ if ( temp.getNext() == trailer){ to_return+=(temp.element().toString()); }else{ to_return+=(temp.element().toString() + ","); } } to_return = to_return + "]"; return to_return; } public void reverse(){ if (size() > 1){ E temp = remove(last()); reverse(); addFirst(temp); } } @Override // iterator created using specific class for PositionList data structures : ElementIterator public Iterator iterator() { return new ElementIterator(this); } public Iterator> positions() { return new MyPositionsIterator(this); } class MyPositionsIterator implements Iterator>{ public MyPositionsIterator (NodePositionList structure){ new_structure = new NodePositionList>(); if (structure.size() != 0){ Position temp; for (temp = structure.first() ; temp!= structure.last() ; temp = structure.next(temp)){ new_structure.addLast(temp); } new_structure.addLast(temp); } } @Override public boolean hasNext() { if (pos == null){ if (new_structure.size() <= 0){ return false; } else { return true; } } else { try { new_structure.next(pos); return true; } catch (BoundaryViolationException err){ return false; } } } @Override public Position next() throws NoSuchElementException { if (hasNext()){ if (pos == null){ pos = new_structure.first(); }else { pos = new_structure.next(pos); } return pos.element(); } else{ throw new NoSuchElementException(); } } @Override public void remove() { throw new UnsupportedOperationException (); } NodePositionList> new_structure; Position> pos = null; } }