001    package data;
002    
003    import java.util.*;
004    
005    import util.SerializableComparator;
006    
007    /**
008     * A StockFromValueCreator for {@link CountingStock CountingStocks}.
009     *
010     * <p>This StockFromValueCreator assumes a potentially infinite source of available items and adds exactly
011     * as many items of each type (i.e. corresponding CatalogItem) as needed to fulfil the requirement.</p>
012     *
013     * @author Steffen Zschaler
014     * @version 2.0 18/08/1999
015     * @since v2.0
016     */
017    public class DefaultCountingStockFromValueCreator extends Object implements StockFromValueCreator {
018    
019        /**
020         * The CatalogItemValue used to determine the CatalogItems' values.
021         */
022        protected CatalogItemValue m_civEvaluator;
023    
024        /**
025         * Create a new DefaultCountingStockFromValueCreator.
026         *
027         * @param civ the CatalogItemValue used to determine the CatalogItems' values.
028         */
029        public DefaultCountingStockFromValueCreator(CatalogItemValue civ) {
030            super();
031    
032            m_civEvaluator = civ;
033        }
034    
035        /**
036         * This StockFromValueCreator assumes a potentially infinite source of available items and adds exactly
037         * as many items of each type (i.e. corresponding CatalogItem) as needed to fulfil the requirement.
038         *
039         * @override Never
040         */
041        public Value fillStock(Stock st, Value v, DataBasket db) {
042            CountingStock cs = (CountingStock)st;
043            Catalog c = st.getCatalog(db);
044    
045            List lCI = new LinkedList(); // Get items from Catalog
046            for (Iterator i = c.iterator(db, false); i.hasNext(); ) {
047                lCI.add(i.next());
048            }
049    
050            if (lCI.size() == 0) {
051                return v;
052            }
053    
054            Collections.sort(lCI, invertedCIValueOrder(m_civEvaluator)); // Sort the items, greates first
055    
056            // building the Stock
057            for (Iterator i = lCI.iterator(); i.hasNext(); ) {
058                CatalogItem ciCurrent = (CatalogItem)i.next();
059                Value vItemValue = m_civEvaluator.getValue(ciCurrent);
060                Value vCurrent = (Value)vItemValue.clone();
061    
062                int nCount = 1;
063                while (vCurrent.compareTo(v) < 0) {
064                    vCurrent.addAccumulating(vItemValue);
065                    nCount++;
066                }
067    
068                if (vCurrent.compareTo(v) > 0) {
069                    nCount--; // correct, if we went too far.
070                    vCurrent.subtractAccumulating(vItemValue);
071                }
072    
073                if (nCount > 0) {
074                    cs.add(ciCurrent.getName(), nCount, db);
075                    v.subtractAccumulating(vCurrent);
076                }
077            }
078    
079            return v;
080        }
081    
082        /**
083         * Helper method that creates a Comparator that orders CatalogItems, highest value first.
084         */
085        public static final Comparator invertedCIValueOrder(final CatalogItemValue civ) {
086            return new SerializableComparator() {
087                public int compare(Object o1, Object o2) {
088                    return civ.getValue((CatalogItem)o2).compareTo(civ.getValue((CatalogItem)o1));
089                }
090            };
091        }
092    }