001    package com.alexkasko.springjdbc.iterable;
002    
003    
004    import java.io.Closeable;
005    import java.util.ArrayList;
006    import java.util.List;
007    
008    /**
009     * Specialized {@link Iterable} partial implementation, returns closable iterators.
010     * This class is not used directly in this library and may be used for
011     * processing possible results for multiple queries in "passive" mode
012     * (no DB resources are used until client call to {@link #iterator()}).
013     * Retains references to returned iterators and closes them on {@link #close()} call.
014     *
015     *
016     * @author alexkasko
017     * Date: 6/21/13
018     */
019    public abstract class CloseableIterable<T> implements Iterable<T>, Closeable {
020        protected List<CloseableIterator<T>> iters = new ArrayList<CloseableIterator<T>>();
021    
022        /**
023         * Implementation should return new {@link CloseableIterator} instance
024         *
025         * @return closeable iterator
026         */
027        protected abstract CloseableIterator<T> closeableIterator();
028    
029        /**
030         * {@inheritDoc}
031         */
032        @Override
033        public CloseableIterator<T> iterator() {
034            CloseableIterator<T> ci = closeableIterator();
035            iters.add(ci);
036            return ci;
037        }
038    
039        /**
040         * {@inheritDoc}
041         */
042        @Override
043        public void close() {
044            for (CloseableIterator<T> ci : iters) {
045                if (null != ci) ci.close();
046            }
047        }
048    
049        /**
050         * Returns {@code true} if all produces iterators are closed
051         *
052         * @return {@code true} if all produces iterators are closed
053         *         {@code false} otherwise
054         */
055        public boolean isClosed() {
056            for (CloseableIterator<T> ci : iters) {
057                if (null != ci && !ci.isClosed()) return false;
058            }
059            return true;
060        }
061    }