001    package data;
002    
003    import java.util.*;
004    
005    /**
006     * A StockFromStockCreator that performs backtracking.
007     *
008     * @author Steffen Zschaler
009     * @version 2.0 18/08/1999
010     * @since v0.5
011     */
012    public class StockFromStockCreatorBT extends StockFromStockCreator {
013    
014        /**
015         * A sorted list of the CatalogItems in the destination Stock's Catalog.
016         */
017        protected List m_lSortedCI;
018    
019        /**
020         * A Map of the items that were added. Needed for undo operations during backtracking.
021         */
022        protected Map m_mplsiItemsAdded = new HashMap();
023    
024        /**
025         * Create a new StockFromStockCreatorBT.
026         *
027         * @param stSource the source Stock.
028         * @param civ the CatalogItemValue used to determine the CatalogItems' values.
029         */
030        public StockFromStockCreatorBT(Stock stSource, CatalogItemValue civ) {
031            super(stSource, civ);
032        }
033    
034        /**
035         * Fill the destination Stock using the same algorithm as in {@link StockFromStockCreator#fillStock}, but
036         * with backtracking.
037         *
038         * @override Never
039         */
040        public Value fillStock(Stock st, Value v, DataBasket db) {
041            Catalog c = st.getCatalog(db);
042    
043            if (c != m_stSource.getCatalog(db)) {
044                throw new CatalogConflictException();
045            }
046    
047            m_lSortedCI = new LinkedList();
048            for (Iterator i = c.iterator(db, false); i.hasNext(); ) {
049                m_lSortedCI.add(i.next());
050            }
051    
052            if (m_lSortedCI.size() == 0) {
053                return v;
054            }
055    
056            Collections.sort(m_lSortedCI,  // Sort the items, greates first
057                    DefaultCountingStockFromValueCreator.invertedCIValueOrder(m_civEvaluator));
058    
059            // fill Stock
060            return doFill(0, v, st, db);
061        }
062    
063        /**
064         * Backtracking step method.
065         *
066         * @override Never
067         */
068        protected Value doFill(int nIdx, Value v, Stock st, DataBasket db) {
069            if (v.isAddZero()) {
070                return v;
071            }
072    
073            if (nIdx >= m_lSortedCI.size()) {
074                return v;
075            }
076    
077            // Attempt to add as many of idx as possible
078            CatalogItem ci = (CatalogItem)m_lSortedCI.get(nIdx);
079            Value vItemValue = m_civEvaluator.getValue(ci);
080    
081            LinkedList lAddedItems = new LinkedList();
082            m_mplsiItemsAdded.put(ci.getName(), lAddedItems);
083    
084            for (Iterator i = m_stSource.get(ci.getName(), db, false); i.hasNext(); ) {
085                if (vItemValue.compareTo(v) <= 0) {
086                    StockItem si = (StockItem)i.next();
087    
088                    try {
089                        i.remove();
090    
091                        st.add(si, db);
092    
093                        v.subtractAccumulating(vItemValue);
094                        lAddedItems.add(si);
095                    }
096                    catch (UnsupportedOperationException uoe) {}
097                } else {
098                    break;
099                }
100            }
101    
102            // if we are not ready yet, go on.
103            if (!v.isAddZero()) {
104    
105                Value vTemp = doFill(nIdx + 1, v, st, db);
106    
107                while ((!vTemp.isAddZero()) && (lAddedItems.size() > 0)) {
108                    // undo unsuccessful filling operation
109                    undoFill(nIdx + 1, v, st, db);
110    
111                    // return one item onto theOrgStock
112                    try {
113                        StockItem si = (StockItem)lAddedItems.removeLast();
114                        st.remove(si, db);
115                        m_stSource.add(si, db);
116    
117                        v.addAccumulating(m_civEvaluator.getValue(ci));
118                    }
119                    catch (data.events.VetoException ve) {}
120    
121                    vTemp = doFill(nIdx + 1, v, st, db);
122                }
123    
124                return vTemp;
125            } else {
126                return v;
127            }
128        }
129    
130        /**
131         * Backtracking back-step  method.
132         *
133         * @override Never
134         */
135        protected void undoFill(int nIdx, Value v, Stock st, DataBasket db) {
136            for (; nIdx < m_lSortedCI.size(); nIdx++) {
137                CatalogItem ci = (CatalogItem)m_lSortedCI.get(nIdx);
138    
139                List lItems = (List)m_mplsiItemsAdded.get(ci.getName());
140    
141                if (lItems != null) {
142                    for (Iterator i = lItems.iterator(); i.hasNext(); ) {
143                        try {
144                            StockItem si = (StockItem)i.next();
145                            i.remove();
146    
147                            st.remove(si, db);
148                            m_stSource.add(si, db);
149    
150                            v.addAccumulating(m_civEvaluator.getValue(ci));
151                        }
152                        catch (data.events.VetoException ex) {}
153                    }
154                }
155            }
156        }
157    }