001/*
002 *                    BioJava development code
003 *
004 * This code may be freely distributed and modified under the
005 * terms of the GNU Lesser General Public Licence.  This should
006 * be distributed with the code.  If you do not have a copy,
007 * see:
008 *
009 *      http://www.gnu.org/copyleft/lesser.html
010 *
011 * Copyright for this code is held jointly by the individual
012 * authors.  These should be listed in @author doc comments.
013 *
014 * For more information on the BioJava project and its aims,
015 * or to join the biojava-l mailing list, visit the home page
016 * at:
017 *
018 *      http://www.biojava.org/
019 *
020 * Created on 09.05.2004
021 * @author Andreas Prlic
022 *
023 */
024
025package org.biojava.nbio.structure;
026
027import java.util.Iterator;
028import java.util.List;
029import java.util.NoSuchElementException;
030
031
032/** 
033 * An iterator over all groups of a structure.
034 * @author Andreas Prlic
035 * @since 1.4
036 * @version %I% %G%
037 */
038
039public class GroupIterator implements Iterator<Group> {
040
041        private Structure structure   ;
042        private int current_model_pos ;
043        private int current_chain_pos ;
044        private int current_group_pos ;
045        private boolean fixed_model   ;
046        
047
048        /**
049         * Constructs a GroupIterator object over all models
050         *
051         * @param struct  a Structure object
052         */
053        public GroupIterator (Structure struct) {
054                structure = struct     ;
055                current_model_pos = 0  ;
056                current_chain_pos = 0  ;
057                current_group_pos = -1 ;
058                fixed_model = false    ;
059        }
060        /**
061         * Constructs a GroupIterator object over a specific model
062         *
063         * @param struct  a Structure object
064         */
065        public GroupIterator (Structure struct, int modelNr) {
066                structure = struct     ;
067                current_model_pos = modelNr;
068                current_chain_pos = 0  ;
069                current_group_pos = -1 ;
070                fixed_model = true     ;
071        }
072
073
074        /** needed to do a copy of iterator ... */
075        private Structure getStructure() { return structure         ;}
076        private int  getModelPos()       { return current_model_pos ;}
077        private void setModelPos(int pos){ current_model_pos = pos  ;}
078        private int  getChainPos()       { return current_chain_pos ;}
079        private void setChainPos(int pos){ current_chain_pos = pos  ;}
080        private int  getGroupPos()       { return current_group_pos ;}
081        private void setGroupPos(int pos){ current_group_pos = pos  ;}
082
083        /**  Creates and returns a copy of this object. */
084        @Override
085        public Object clone () {
086
087                GroupIterator gr = new GroupIterator(this.getStructure()) ;
088                gr.setModelPos(this.getModelPos());
089                gr.setChainPos(this.getChainPos());
090                gr.setGroupPos(this.getGroupPos());
091                gr.fixed_model = this.fixed_model;
092                return gr ;
093
094        }
095
096
097        /** is there a group after the current one in the structure? */
098        @Override
099        public boolean hasNext() {
100                return hasSubGroup(current_model_pos,current_chain_pos , current_group_pos +1) ;
101        }
102
103        /** recursive method to determine if there is a next group. Helper
104         * method for hasNext().
105         * @see #hasNext
106         */
107        private boolean hasSubGroup(int tmp_model,int tmp_chain,int tmp_group) {
108
109                if (tmp_model >= structure.nrModels()) {
110                        return false;
111                }
112
113                List<Chain> model = structure.getModel(tmp_model);
114
115                if (tmp_chain >= model.size()) {
116                        if(fixed_model)
117                                return false;
118                        return hasSubGroup(tmp_model + 1, 0, 0);
119                }
120
121                Chain chain = model.get(tmp_chain);
122
123                // start search at beginning of next chain.
124                return tmp_group < chain.getAtomLength() || hasSubGroup(tmp_model, tmp_chain + 1, 0);
125
126        }
127
128        /** Get the model number of the current model.
129         *
130         * @return the number of the model
131         */
132        public int getCurrentModel(){
133
134                return current_model_pos;
135        }
136
137        /** Get the current Chain. Returns null if we are at the end of the iteration.
138         *
139         * @return the Chain of the current position
140         */
141        public Chain getCurrentChain(){
142                if ( current_model_pos >= structure.nrModels()){
143                        return null;
144                }
145
146                List<Chain> model =  structure.getModel(current_model_pos);
147
148                if ( current_chain_pos >= model.size() ){
149                        return null;
150                }
151
152                return model.get(current_chain_pos);
153
154        }
155
156        /** get next Group.
157         * @return next Group
158         * @throws NoSuchElementException ...
159         */
160        @Override
161        public Group next()
162        throws NoSuchElementException
163        {
164
165                return getNextGroup(current_model_pos,current_chain_pos,current_group_pos+1);
166        }
167
168        /** recursive method to retrieve the next group. Helper
169         * method for gext().
170         * @see #next
171         */
172        private Group getNextGroup(int tmp_model,int tmp_chain,int tmp_group)
173        throws NoSuchElementException
174        {
175
176                if ( tmp_model >= structure.nrModels()){
177                        throw new NoSuchElementException("arrived at end of structure!");
178                }
179
180                List<Chain> model = structure.getModel(tmp_model);
181
182                if ( tmp_chain >= model.size() ){
183                        if(fixed_model)
184                                throw new NoSuchElementException("arrived at end of model!");
185                        return getNextGroup(tmp_model+1,0,0);
186                }
187
188                Chain     chain = model.get(tmp_chain);
189
190                if (tmp_group  >= chain.getAtomLength()){
191                        // start search at beginning of next chain.
192                        return getNextGroup(tmp_model,tmp_chain+1,0);
193                } else {
194                        current_model_pos = tmp_model;
195                        current_chain_pos = tmp_chain;
196                        current_group_pos = tmp_group;
197                        return chain.getAtomGroup(current_group_pos);
198                }
199
200        }
201
202        /** does nothing .
203         */
204        @Override
205        public void remove() {
206                throw new UnsupportedOperationException("Cannot call remove() for GroupIterator");
207        }
208
209
210}
211