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/** An iterator over all groups of a structure.
033 * @author Andreas Prlic
034 * @since 1.4
035 * @version %I% %G%
036 */
037
038public class GroupIterator implements Iterator<Group> {
039
040        Structure structure   ;
041        int current_model_pos ;
042        int current_chain_pos ;
043        int current_group_pos ;
044
045        /**
046         * Constructs a GroupIterator object.
047         *
048         * @param struct  a Structure object
049         */
050
051        public GroupIterator (Structure struct) {
052                structure = struct     ;
053                current_model_pos = 0  ;
054                current_chain_pos = 0  ;
055                current_group_pos = -1 ;
056
057        }
058
059
060        /** needed to do a copy of iterator ... */
061        private Structure getStructure() { return structure         ;}
062        private int  getModelPos()       { return current_model_pos ;}
063        private void setModelPos(int pos){ current_model_pos = pos  ;}
064        private int  getChainPos()       { return current_chain_pos ;}
065        private void setChainPos(int pos){ current_chain_pos = pos  ;}
066        private int  getGroupPos()       { return current_group_pos ;}
067        private void setGroupPos(int pos){ current_group_pos = pos  ;}
068
069        /**  Creates and returns a copy of this object. */
070        @Override
071        public Object clone () {
072
073                GroupIterator gr = new GroupIterator(this.getStructure()) ;
074                gr.setModelPos(this.getModelPos());
075                gr.setChainPos(this.getChainPos());
076                gr.setGroupPos(this.getGroupPos());
077                return gr ;
078
079        }
080
081
082        /** is there a group after the current one in the structure? */
083        @Override
084        public boolean hasNext() {
085                return hasSubGroup(current_model_pos,current_chain_pos , current_group_pos +1) ;
086        }
087
088        /** recursive method to determine if there is a next group. Helper
089         * method for hasNext().
090         * @see #hasNext
091         */
092        private boolean hasSubGroup(int tmp_model,int tmp_chain,int tmp_group) {
093
094                if (tmp_model >= structure.nrModels()) {
095                        return false;
096                }
097
098                List<Chain> model = structure.getModel(tmp_model);
099
100                if (tmp_chain >= model.size()) {
101                        return hasSubGroup(tmp_model + 1, 0, 0);
102                }
103
104                Chain chain = model.get(tmp_chain);
105
106                // start search at beginning of next chain.
107                return tmp_group < chain.getAtomLength() || hasSubGroup(tmp_model, tmp_chain + 1, 0);
108
109        }
110
111        /** Get the model number of the current model.
112         *
113         * @return the number of the model
114         */
115        public int getCurrentModel(){
116
117                return current_model_pos;
118        }
119
120        /** Get the current Chain. Returns null if we are at the end of the iteration.
121         *
122         * @return the Chain of the current position
123         */
124        public Chain getCurrentChain(){
125                if ( current_model_pos >= structure.nrModels()){
126                        return null;
127                }
128
129                List<Chain> model =  structure.getModel(current_model_pos);
130
131                if ( current_chain_pos >= model.size() ){
132                        return null;
133                }
134
135                return model.get(current_chain_pos);
136
137        }
138
139        /** get next Group.
140         * @return next Group
141         * @throws NoSuchElementException ...
142         */
143        @Override
144        public Group next()
145        throws NoSuchElementException
146        {
147
148                return getNextGroup(current_model_pos,current_chain_pos,current_group_pos+1);
149        }
150
151        /** recursive method to retrieve the next group. Helper
152         * method for gext().
153         * @see #next
154         */
155        private Group getNextGroup(int tmp_model,int tmp_chain,int tmp_group)
156        throws NoSuchElementException
157        {
158
159                if ( tmp_model >= structure.nrModels()){
160                        throw new NoSuchElementException("arrived at end of structure!");
161                }
162
163                List<Chain> model = structure.getModel(tmp_model);
164
165                if ( tmp_chain >= model.size() ){
166                        return getNextGroup(tmp_model+1,0,0);
167                }
168
169                Chain     chain = model.get(tmp_chain);
170
171                if (tmp_group  >= chain.getAtomLength()){
172                        // start search at beginning of next chain.
173                        return getNextGroup(tmp_model,tmp_chain+1,0);
174                } else {
175                        current_model_pos = tmp_model;
176                        current_chain_pos = tmp_chain;
177                        current_group_pos = tmp_group;
178                        return chain.getAtomGroup(current_group_pos);
179                }
180
181        }
182
183        /** does nothing .
184         */
185        @Override
186        public void remove() {
187                throw new UnsupportedOperationException("Cannot call remove() for GroupIterator");
188        }
189
190
191}
192