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 }