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 }