001    /*
002     *  www.ti.bfh.ch
003     *
004     *  Copyright 2007, Berne University of Applied Sciences, 
005     *  School of Engineering and Information Technology
006     *  and individual contributors as indicated by the @authors tag.
007     *
008     *  This is free software; you can redistribute it and/or modify it under the terms of the 
009     *  GNU Lesser General Public License as published by the Free Software Foundation; 
010     *  either version 3 of the License, or (at your option) any later version.
011     *
012     *  This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
013     *  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
014     *  See the GNU Lesser General Public License for more details.
015     *
016     *  You should have received a copy of the GNU Lesser General Public License along with this software; 
017     *  if not, see <http://www.gnu.org/licenses/>.
018     *
019     */
020    package ch.bfh.algo.core.sequence;
021    
022    
023    import java.util.NoSuchElementException;
024    
025    import ch.bfh.algo.InvalidAccessorException;
026    
027    
028    
029    public class LinkedIterator<E,P extends GenericLinkedPosition<E,P>>{
030    
031            private final GenericLinkedSequence<E,P> sequence;
032            private final LinkedCursor<E,P> cursor;
033            private P cache=null;
034            
035            public LinkedIterator(GenericLinkedSequence<E,P> sequence, P before, P after){
036                    this.sequence=sequence;
037                    this.cursor=new LinkedCursor<E,P>(before,after);
038            }
039            
040            public boolean hasNext(){
041                    return this.cursor.getNext()!=this.sequence.tail();
042            }
043    
044            public boolean hasPrevious(){
045                    return this.cursor.getPrevious()!=this.sequence.head();
046            }
047    
048            public P nextPosition(){
049                    if(!this.hasNext()) throw new NoSuchElementException();
050                    this.cache=this.cursor.getNext();
051                    this.cursor.moveNext();
052                    return this.cache;
053            }
054            
055            public E nextElement(){
056                    return this.nextPosition().element();
057            }
058    
059            public int nextIndex(){
060                    if(!this.hasNext()) return this.sequence.size();
061                    return this.sequence.rank(this.cursor.getNext());
062            }
063    
064            public P previousPosition(){
065                    if(!this.hasPrevious()) throw new NoSuchElementException();
066                    this.cache=this.cursor.getPrevious();
067                    this.cursor.movePrevious();
068                    return this.cache;
069            }
070    
071            public E previousElement(){
072                    return this.previousPosition().element();
073            }
074    
075            public int previousIndex(){
076                    if(!this.hasPrevious()) return -1;
077                    return this.sequence.rank(this.cursor.getPrevious());
078            }
079            
080            private void setIllegalState(){
081                    this.cache=null;
082            }
083            
084            private boolean isIllegalSate(){
085                    return this.cache==null;
086            }
087    
088            public void addElement(E element){
089                    this.sequence.insertBetween(this.cursor.getPrevious(),this.cursor.getNext(),element);
090                    this.setIllegalState();
091            }
092    
093            public void remove(){
094                    if(this.isIllegalSate()) throw new IllegalStateException();
095                    try{
096                            this.sequence.delete(this.cache);
097                    }catch(InvalidAccessorException e){
098                            throw new IllegalStateException();
099                    }
100                    finally{this.setIllegalState();}
101            }
102    
103            public void setElement(E element){
104                    if(this.isIllegalSate()) throw new IllegalStateException();
105                    try{
106                            this.sequence.replace(this.cache,element);
107                    }catch(InvalidAccessorException e){
108                            this.setIllegalState();
109                            throw new IllegalStateException();
110                    }
111            }
112    
113            public void finalize() throws Throwable{
114                    synchronized(this.sequence){
115                            this.cursor.detach();
116                    }
117                    super.finalize();
118            }
119    
120    }