001    package data.filters;
002    
003    import data.*;
004    import data.events.*;
005    
006    import java.util.*;
007    
008    /**
009     * StockFilter for StoringStocks.
010     *
011     * <p>The filter condition can be defined by overriding method
012     * {@link #contains(data.StockItem, data.DataBasket)}.</p>
013     *
014     * @author Steffen Zschaler
015     * @version 2.0 19/08/1999
016     * @since v2.0
017     */
018    public abstract class StoringStockFilter<T extends StockItem, CT extends CatalogItem> 
019                          extends AbstractStockFilter<T, CT> implements StoringStock<T, CT> {
020    
021        /**
022         * Create a new StoringStockFilter.
023         *
024         * @param ssSource the source Stock.
025         */
026        public StoringStockFilter(StoringStock<T, CT> ssSource) {
027            super(ssSource);
028        }
029    
030        /**
031         * Get all StockItems for a given key that are contained in the filtered Stock.
032         *
033         * @override Never
034         */
035        public Iterator<T> get(final String sKey, final DataBasket db, final boolean fForEdit) {
036            class I implements Iterator<T> {
037                protected Iterator<T> m_iIterator = m_stSource.get(sKey, db, fForEdit);
038                protected T m_siCurrent;
039                protected T m_siNext;
040    
041                public boolean hasNext() {
042                    return findNext(false);
043                }
044    
045                public T next() {
046                    if (!findNext(true)) {
047                        throw new NoSuchElementException();
048                    }
049    
050                    return m_siCurrent;
051                }
052    
053                public void remove() {
054                    if (m_siCurrent == null) {
055                        throw new IllegalStateException();
056                    }
057    
058                    try {
059                        StoringStockFilter.this.remove(m_siCurrent, db);
060                    }
061                    catch (VetoException ve) {
062                        throw new UnsupportedOperationException();
063                    }
064                }
065    
066                private boolean findNext(boolean fGet) {
067                    if (m_siNext != null) {
068                        if (fGet) {
069                            m_siCurrent = m_siNext;
070                            m_siNext = null;
071                        }
072    
073                        return true;
074                    }
075    
076                    while (m_iIterator.hasNext()) {
077                        T si = m_iIterator.next();
078    
079                        if (contains(si, db)) {
080                            if (fGet) {
081                                m_siCurrent = si;
082                                m_siNext = null;
083                            } else {
084                                m_siNext = si;
085                            }
086    
087                            return true;
088                        }
089                    }
090    
091                    return false;
092                }
093            }
094    
095            return new I();
096        }
097    
098        /**
099         * Count all StockItems for a given key that are contained in the filtered Stock.
100         *
101         * @override Never
102         */
103        public int countItems(String sKey, DataBasket db) {
104            int nCount = 0;
105    
106            for (Iterator<T> i = get(sKey, db, false); i.hasNext(); ) {
107                nCount++;
108                i.next();
109            }
110    
111            return nCount;
112        }
113    
114        /**
115         * Filter condition: Check whether a given item is contained in the filtered Stock.
116         *
117         * @override Always
118         *
119         * @param si the StockItem to be checked.
120         * @param db the DataBasket to be used to check visibility.
121         *
122         * @return true if the given item is to be contained in the filtered Stock.
123         */
124        public abstract boolean contains(StockItem si, DataBasket db);
125    
126        /**
127         * Check whether the given Stock is contained in the filtered Stock.
128         *
129         * @override Never
130         */
131        public boolean containsStock(Stock<T, CT> st, DataBasket db) {
132            boolean fResult = m_stSource.containsStock(st, db);
133    
134            if (fResult) {
135                for (Iterator<T> i = st.iterator(db, false); i.hasNext(); ) {
136                    if (!contains(i.next(), db)) {
137                        return false;
138                    }
139                }
140            }
141    
142            return fResult;
143        }
144    }