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.AbstractList;
024    
025    import ch.bfh.algo.BoundaryViolationException;
026    import ch.bfh.algo.EmptySequenceException;
027    import ch.bfh.algo.InvalidAccessorException;
028    import ch.bfh.algo.Position;
029    import ch.bfh.algo.core.GenericSequence;
030    import ch.bfh.algo.core.position.PositionIterator;
031    import ch.bfh.algo.core.position.PositionListIterator;
032    import ch.bfh.algo.core.position.PositionListIteratorAdapter;
033    import ch.bfh.algo.sequence.SequenceFactory;
034    
035    
036    public class GenericArraySequence<E,P extends GenericArrayPosition<E,P>> extends AbstractList<E> implements GenericSequence<E,P>{
037            
038            private PositionArray<E,P> array;
039            private SequenceFactory<P> factory;
040            
041            public GenericArraySequence(int size, SequenceFactory<P> factory, ArrayStrategy<P> strategy){
042                    this.factory=factory;
043                    this.array=new PositionArray<E,P>(size,strategy);
044            }
045            
046        private void validate(P position) throws InvalidAccessorException{
047            if(position==null || this!=position.container()) throw new InvalidAccessorException();
048        }
049        
050            public boolean encloses(Position<?> position) {
051                    try{return this.encloses(this.factory.cast(position));}
052                    catch(ClassCastException e){return false;}
053            }
054    
055        public boolean encloses(P position){
056            try{this.validate(position); return true;}
057            catch(InvalidAccessorException e){return false;}
058        }
059        
060            public E get(int index) throws IndexOutOfBoundsException{
061                    return this.array.get(index).element();
062            }
063    
064            public int size(){
065                    return this.array.size();
066            }
067    
068            public P first() throws EmptySequenceException{
069                    if(!this.isEmpty())return this.array.get(0);
070                    else throw new EmptySequenceException();
071            }
072    
073            public P last() throws EmptySequenceException{
074                    if(!this.isEmpty())return this.array.get(this.size()-1);
075                    else throw new EmptySequenceException();
076            }
077    
078            public P before(Position<?> position) throws InvalidAccessorException, BoundaryViolationException {
079                    try{return this.before(this.factory.cast(position));}
080                    catch(ClassCastException e){throw new InvalidAccessorException();}
081            }
082    
083            public P before(P position) throws InvalidAccessorException, BoundaryViolationException{
084                    this.validate(position);
085                    int index=position.getRank()-1;
086                    if(index>=0) return this.array.get(index);
087                    else throw new BoundaryViolationException();
088            }
089    
090            public P after(Position<?> position) throws InvalidAccessorException, BoundaryViolationException {
091                    try{return this.after(this.factory.cast(position));}
092                    catch(ClassCastException e){throw new InvalidAccessorException();}
093            }
094    
095            public P after(P position) throws InvalidAccessorException, BoundaryViolationException{
096                    this.validate(position);
097                    int index=position.getRank()+1;
098                    if(index<this.size()) return this.array.get(index);
099                    else throw new BoundaryViolationException();
100            }
101            
102            public P insertBefore(Position<?> position, E element) throws InvalidAccessorException {
103                    try{return this.insertBefore(this.factory.cast(position),element);}
104                    catch(ClassCastException e){throw new InvalidAccessorException();}
105            }
106    
107            public P insertBefore(P position, E element) throws InvalidAccessorException{
108                    this.validate(position);
109                    return this.insertBefore(this.rank(position),element);
110            }
111    
112            private P insertBefore(int index, E element){
113                    P position=this.factory.createPosition();
114                    ConcreteLocator<E,P> locator=new ConcreteLocator<E,P>();
115                    locator.setElement(element);
116                    locator.setPosition(position);
117                    position.setLocator(locator);
118                    position.setContainer(this);
119                    this.array.insert(index,position);
120                    return position;
121            }
122            
123            public void add(int index, E element) throws IndexOutOfBoundsException{
124                    this.insertBefore(index,element);
125            }
126    
127            public P insertAfter(Position<?> position, E element) throws InvalidAccessorException {
128                    try{return this.insertAfter(this.factory.cast(position),element);}
129                    catch(ClassCastException e){throw new InvalidAccessorException();}
130            }
131    
132            public P insertAfter(P position, E element) throws InvalidAccessorException{
133                    this.validate(position);
134                    return this.insertBefore(this.rank(position)+1,element);
135            }
136    
137            public P insert(E element){
138                    return this.insertBefore(this.size(),element);
139            }
140    
141            public P position(int rank) throws IndexOutOfBoundsException{
142                    return this.array.get(rank);
143            }
144    
145            public int rank(Position<?> position) {
146                    try{return this.rank(this.factory.cast(position));}
147                    catch(ClassCastException e){return -1;}
148            }
149    
150            public int rank(P position){
151                    try{
152                            this.validate(position);
153                            return position.getRank();
154                    }catch(InvalidAccessorException e){return -1;}
155            }
156    
157            public E replace(Position<?> position, E element) throws InvalidAccessorException {
158                    try{return this.replace(this.factory.cast(position),element);}
159                    catch(ClassCastException e){throw new InvalidAccessorException();}
160            }
161    
162            public E replace(P position, E element) throws InvalidAccessorException{
163                    this.validate(position);
164                    return position.replace(position,element);
165            }
166            
167            public E element(Position<?> position){
168                    try{return this.element(this.factory.cast(position));}
169                    catch(ClassCastException e){throw new InvalidAccessorException();}
170            }
171            
172            public E element(P position){
173                    this.validate(position);
174                    return position.element();
175            }
176            
177            public E set(int index, E element) throws IndexOutOfBoundsException{
178                    P p=this.array.get(index);
179                    return p.replace(p,element);
180            }
181    
182            public E delete(Position<?> position) throws InvalidAccessorException {
183                    try{return this.delete(this.factory.cast(position));}
184                    catch(ClassCastException e){throw new InvalidAccessorException();}
185            }
186    
187            public E delete(P position) throws InvalidAccessorException{
188                    this.validate(position);
189                    return this.remove(position.getRank());
190            }
191    
192            public E remove(int index) throws IndexOutOfBoundsException{
193                    P position=this.array.delete(index);
194                    E element=position.element();
195            position.locator().setPosition(null);
196            position.setLocator(null);
197            position.setContainer(null);
198            return element;
199            }
200    
201            public void swap(Position<?> position0, Position<?> position1) throws InvalidAccessorException {
202                    try{this.swap(this.factory.cast(position0),this.factory.cast(position1));}
203                    catch(ClassCastException e){throw new InvalidAccessorException();}
204            }
205    
206            public void swap(P position0, P position1) throws InvalidAccessorException{
207            this.validate(position0);
208            this.validate(position1);
209            position0.swap(position0,position1);
210            }
211            
212            public PositionIterator<E,P> positionIterator(){
213                    return this.positionListIterator(0);
214            }
215            
216            public PositionListIterator<E,P> positionListIterator(final int rank){
217                    return new PositionListIteratorAdapter<E,P>(GenericArraySequence.this.array.listIterator(rank));
218            }
219            
220            public PositionListIterator<E,P> positionListIterator(){
221                    return this.positionListIterator(0);
222            }
223            
224    }