001package net.automatalib.commons.util.collections;
002
003import java.util.Iterator;
004
005
006public abstract class ThreeLevelIterator<L1, L2, L3, O> implements Iterator<O> {
007        
008        private static class Outer<L1,L2> {
009                private L1 l1Item;
010                private L2 l2Item;
011        }
012        
013        private class OuterIterator extends TwoLevelIterator<L1,L2,Outer<L1,L2>> {
014
015                private final Outer<L1,L2> value = new Outer<>();
016                
017                public OuterIterator(Iterator<L1> l1Iterator) {
018                        super(l1Iterator);
019                }
020
021                @Override
022                protected Iterator<L2> l2Iterator(L1 l1Object) {
023                        return ThreeLevelIterator.this.l2Iterator(l1Object);
024                }
025
026                @Override
027                protected Outer<L1, L2> combine(L1 l1Object, L2 l2Object) {
028                        value.l1Item = l1Object;
029                        value.l2Item = l2Object;
030                        return value;
031                }
032        }
033        
034        private class InnerIterator extends TwoLevelIterator<Outer<L1,L2>,L3,O> {
035                public InnerIterator(Iterator<Outer<L1, L2>> outerIterator) {
036                        super(outerIterator);
037                }
038                @Override
039                protected Iterator<L3> l2Iterator(Outer<L1, L2> outer) {
040                        return ThreeLevelIterator.this.l3Iterator(outer.l1Item, outer.l2Item);
041                }
042                @Override
043                protected O combine(Outer<L1, L2> outer, L3 l3Object) {
044                        return ThreeLevelIterator.this.combine(outer.l1Item, outer.l2Item, l3Object);
045                }
046        }
047        
048        private final InnerIterator innerIterator;
049        
050        public ThreeLevelIterator(Iterator<L1> l1Iterator) {
051                OuterIterator outerIterator = new OuterIterator(l1Iterator);
052                this.innerIterator = new InnerIterator(outerIterator);
053        }
054
055        
056        protected abstract Iterator<L2> l2Iterator(L1 l1Object);
057        protected abstract Iterator<L3> l3Iterator(L1 l1Object, L2 l2Object);
058        
059        
060        protected abstract O combine(L1 l1Object, L2 l2Object, L3 l3Object);
061
062
063        /* (non-Javadoc)
064         * @see java.util.Iterator#hasNext()
065         */
066        @Override
067        public boolean hasNext() {
068                return innerIterator.hasNext();
069        }
070
071
072        /* (non-Javadoc)
073         * @see java.util.Iterator#next()
074         */
075        @Override
076        public O next() {
077                return innerIterator.next();
078        }
079
080
081        /* (non-Javadoc)
082         * @see java.util.Iterator#remove()
083         */
084        @Override
085        public void remove() {
086                innerIterator.remove();
087        }       
088        
089        
090
091}