001    package org.cocome.tradingsystem.systests.util;
002    
003    import java.util.ArrayList;
004    import java.util.HashSet;
005    import java.util.List;
006    import java.util.Random;
007    import java.util.Set;
008    
009    import org.cocome.tradingsystem.systests.interfaces.IEnterprise;
010    import org.cocome.tradingsystem.systests.interfaces.IProduct;
011    
012    /**
013     * This class is used to generate random but reproducable products.
014     * 
015     * @author Benjamin Hummel
016     * @author Christian Pfaller
017     * @author $Author: pfaller $
018     * @version $Rev: 60 $
019     * @levd.rating GREEN Rev: 60
020     */
021    public class ProductGenerator {
022    
023            /** Available alphabet for product name generation. */
024            private static final String ALPHA = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-_";
025    
026            /** The random number generator used. */
027            private final Random rng;
028    
029            /** The enterprise used for creating products. */
030            private final IEnterprise enterprise;
031    
032            /** The set of used barcodes to avoid repetition. */
033            private final Set<Integer> usedBarcodes = new HashSet<Integer>();
034    
035            /** The set of used names to avoid repetition. */
036            private final Set<String> usedNames = new HashSet<String>();
037    
038            /** A list of all products generated so far. */
039            private final List<GeneratedProduct> generatedProducts = new ArrayList<GeneratedProduct>();
040    
041            /**
042             * Construct a new product generator.
043             * 
044             * @param randomSeed
045             *            the random seed used for initializing the random number
046             *            generator.
047             * @param enterprise
048             *            the enterprise used for creating products.
049             */
050            public ProductGenerator(long randomSeed, IEnterprise enterprise) {
051                    rng = new Random(randomSeed);
052                    this.enterprise = enterprise;
053            }
054    
055            /** Returns the number of products generated so far. */
056            public int getNumberOfProducts() {
057                    return generatedProducts.size();
058            }
059    
060            /**
061             * Returns the product generated when <code>i</code> products had been
062             * generated already.
063             */
064            public GeneratedProduct getGeneratedProduct(int i) {
065                    return generatedProducts.get(i);
066            }
067    
068            /** Generate the given number of random products. */
069            public void generate(int n) throws Exception {
070                    for (int i = 0; i < n; ++i) {
071                            generate();
072                    }
073            }
074            
075    
076            /** Generate a single random product. 
077             * @return index of new product
078             * @throws Exception
079             */
080            public int generate() throws Exception {
081    
082                    int barcode = getUnusedBarcode();
083                    int purchasePrice = rng.nextInt(100000);
084    
085                    String name;
086                    do {
087                            name = "Prod";
088                            for (int i = 0; i < 4; ++i) {
089                                    name += ALPHA.charAt(rng.nextInt(ALPHA.length()));
090                            }
091                    } while (usedNames.contains(name));
092    
093                    IProduct product = enterprise.createProduct(barcode, purchasePrice,
094                                    name);
095                    generatedProducts.add(new GeneratedProduct(barcode, purchasePrice,
096                                    name, product));
097                    
098                    return generatedProducts.size() - 1;
099            }
100    
101            /**
102             * Returns a new barcode which is not already used for any product.
103             */
104            public int getUnusedBarcode() {
105                    int barcode = 0;
106                    do {
107                            barcode = rng.nextInt(1000000);
108                    } while (usedBarcodes.contains(barcode));
109                    return barcode;
110            }
111    
112    }