Coverage Report - net.sourceforge.combean.util.GNestedIterator
 
Classes in this File Line Coverage Branch Coverage Complexity
GNestedIterator
97%
30/31
77%
46/60
1,889
 
 1  
 /*
 2  
     This file is part of Combean.
 3  
 
 4  
     Combean is free software; you can redistribute it and/or modify
 5  
     it under the terms of the GNU General Public License as published by
 6  
     the Free Software Foundation; either version 2 of the License, or
 7  
     (at your option) any later version.
 8  
 
 9  
     Combean is distributed in the hope that it will be useful,
 10  
     but WITHOUT ANY WARRANTY; without even the implied warranty of
 11  
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 12  
     GNU General Public License for more details.
 13  
 
 14  
     You should have received a copy of the GNU General Public License
 15  
     along with Combean; if not, write to the Free Software
 16  
     Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 17  
 */
 18  
 package net.sourceforge.combean.util;
 19  
 
 20  
 import net.sourceforge.combean.util.except.UnsupportedMethodException;
 21  
 import net.sourceforge.combean.interfaces.base.ResettableIterator;
 22  
 
 23  
 /**
 24  
  * An iterator composed of
 25  
  * 
 26  
  * - an outer iterator
 27  
  * - a closure that generates an inner iterator for every element of the outer
 28  
  * iteration. It is called with the current outer iteration value as argument.
 29  
  * 
 30  
  * The nested iterator iterates through all pairs of the outer and inner iteration
 31  
  * and returns ONLY the element of the inner iteration as result of next().
 32  
  */
 33  
 class GNestedIterator implements Iterator {
 34  
 
 35  
     private Iterator itOuter;
 36  
     private Closure getInnerItForOuter;
 37  
     
 38  
     private Iterator itInner;
 39  
     private boolean outerTerminated;
 40  
     private boolean allTerminated;
 41  
     private Object outerObject;
 42  
     
 43  
     public GNestedIterator(Iterable outerIterable, Closure getInnerItForOuter) {
 44  25
         init(outerIterable.iterator(), getInnerItForOuter);
 45  
     }
 46  
     
 47  
     public GNestedIterator(Iterator itOuter, Closure getInnerItForOuter) {
 48  1905
         init(itOuter, getInnerItForOuter);
 49  
     }
 50  
     
 51  
     private init(Iterator itOuter, Closure getInnerItForOuter) {
 52  1930
         this.itOuter = itOuter;
 53  1930
         this.getInnerItForOuter = getInnerItForOuter;
 54  
         
 55  1930
         this.outerTerminated = false;
 56  1930
         this.allTerminated = false;
 57  1930
             nextOuter();
 58  
         
 59  1925
         if (this.outerTerminated) {
 60  5
             this.allTerminated = true;
 61  
         }
 62  
     }
 63  
     
 64  
     protected Object getOuter() {
 65  290
         return this.outerObject;
 66  
     }
 67  
 
 68  
     public void remove() {
 69  0
             throw new UnsupportedMethodException();
 70  
     }
 71  
 
 72  
     boolean hasNext() {
 73  9960
         if (this.allTerminated) {
 74  5
             return false;
 75  
         }
 76  9955
             advanceOuterToNonEmptyInner();
 77  9955
             return !this.outerTerminated || this.itInner.hasNext();
 78  
     }
 79  
     
 80  
     Object next() {
 81  6805
         advanceOuterToNonEmptyInner();
 82  6805
         assert this.itInner.hasNext();
 83  6805
         Object innerObject = this.itInner.next();
 84  6805
         return innerObject;
 85  
     }
 86  
     
 87  
     private boolean nextOuter() {
 88  8580
         if (!itOuter.hasNext()) {
 89  1925
             this.outerTerminated = true;
 90  
         }
 91  
         else {
 92  6655
                 this.outerObject = this.itOuter.next();
 93  6655
                 Object itInnerDef = this.getInnerItForOuter.call(this.outerObject);
 94  6650
                 if (itInnerDef instanceof Iterable) {
 95  50
                     this.itInner = itInnerDef.iterator();
 96  
                 }
 97  
                 else {
 98  6600
                     this.itInner = itInnerDef;
 99  
                 }
 100  6650
             assert this.itInner != null;
 101  
         }
 102  8575
         return !this.outerTerminated;
 103  
     }
 104  
 
 105  
     
 106  
     private void advanceOuterToNonEmptyInner() {
 107  21490
         while (!this.itInner.hasNext()) {
 108  6650
             if (!nextOuter()) {
 109  1920
                 break;
 110  
             }
 111  
         }
 112  
     }
 113  
 }