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 }