001    // Copyright 2007 The Apache Software Foundation
002    //
003    // Licensed under the Apache License, Version 2.0 (the "License");
004    // you may not use this file except in compliance with the License.
005    // You may obtain a copy of the License at
006    //
007    //     http://www.apache.org/licenses/LICENSE-2.0
008    //
009    // Unless required by applicable law or agreed to in writing, software
010    // distributed under the License is distributed on an "AS IS" BASIS,
011    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012    // See the License for the specific language governing permissions and
013    // limitations under the License.
014    
015    package org.apache.tapestry5.test;
016    
017    import java.io.*;
018    import static java.lang.String.format;
019    import java.util.ArrayList;
020    import java.util.List;
021    import java.util.Random;
022    
023    /**
024     * Provides access to random data that can be used when populating a test database with "reasonable" data. The majority
025     * of this is access to random words from an american english dictionary, which can be strung together to form names,
026     * sentences and paragraphs.
027     */
028    public final class RandomDataSource
029    {
030        private final Random random = new Random(System.currentTimeMillis());
031    
032        private final List<String> words = new ArrayList<String>();
033    
034        public RandomDataSource()
035        {
036            for (int i = 0; i < 4; i++)
037                readWords("english." + i);
038    
039            for (int i = 0; i < 3; i++)
040                readWords("american." + i);
041    
042            System.out.printf("Dictionary contains %d words\n", words.size());
043        }
044    
045        private void readWords(String name)
046        {
047            System.out.println("Reading " + name + " ...");
048    
049            int count = 0;
050    
051            InputStream is = getClass().getResourceAsStream(name);
052    
053            if (is == null) throw new RuntimeException(format("File '%s' not found.", name));
054    
055            try
056            {
057                BufferedInputStream bis = new BufferedInputStream(is);
058                InputStreamReader isr = new InputStreamReader(bis);
059                LineNumberReader r = new LineNumberReader(isr);
060    
061                while (true)
062                {
063                    String word = r.readLine();
064    
065                    if (word == null) break;
066    
067                    count++;
068                    words.add(word);
069                }
070    
071                r.close();
072            }
073            catch (IOException ex)
074            {
075                throw new RuntimeException(format("Error reading '%s': %s", name + ex.getMessage()), ex);
076            }
077    
078            System.out.printf("... %d words\n", count);
079        }
080    
081        public boolean maybe(int percent)
082        {
083            assert percent > 0 && percent <= 100;
084    
085            return random.nextInt(100) < percent;
086        }
087    
088        public int random(int min, int max)
089        {
090            assert min <= max;
091    
092            return random.nextInt(max - min + 1) + min;
093        }
094    
095        /**
096         * Returns a random word frm the dictionary. These words are usually all lowercase.
097         */
098        public String word()
099        {
100            int index = random.nextInt(words.size());
101    
102            return words.get(index);
103        }
104    
105        /**
106         * Returns a random word, capitalized. Useful when create random names.
107         */
108        public String capitalizedWord()
109        {
110            String word = word();
111    
112            char[] chars = word.toCharArray();
113    
114            chars[0] = Character.toUpperCase(chars[0]);
115    
116            return new String(chars);
117        }
118    
119        /**
120         * Returns a word that is "safe" for use in an email address.
121         */
122        public String safeWord()
123        {
124            String word = word();
125    
126            int x = word.indexOf('\'');
127    
128            return x < 0 ? word : word.substring(0, x);
129        }
130    
131        /**
132         * Returns a random value from the list of values supplied.
133         */
134        public <T> T oneOf(T... values)
135        {
136            assert values.length > 0;
137    
138            int index = random.nextInt(values.length);
139    
140            return values[index];
141        }
142    
143        /**
144         * Returns a random enum value, given the enum type.
145         */
146        public <T extends Enum> T oneOf(Class<T> enumClass)
147        {
148            return oneOf(enumClass.getEnumConstants());
149        }
150    
151        /**
152         * Creates a space-separated list of random words. If in sentence form, then the first word is capitalized, and a
153         * period is appended.
154         *
155         * @param minWords   minimun number of words in the list
156         * @param maxWords   maximum number of words in the list
157         * @param asSentence if true, the output is "dressed up" as a non-sensical sentence
158         * @return the word list / sentence
159         */
160        public String wordList(int minWords, int maxWords, boolean asSentence)
161        {
162            assert minWords <= maxWords;
163            assert minWords > 0;
164    
165            StringBuilder builder = new StringBuilder();
166    
167            int count = random(minWords, maxWords);
168    
169            for (int i = 0; i < count; i++)
170            {
171    
172                if (i > 0) builder.append(' ');
173    
174                if (i == 0 && asSentence)
175                    builder.append(capitalizedWord());
176                else
177                    builder.append(word());
178            }
179    
180            if (asSentence) builder.append('.');
181    
182            return builder.toString();
183        }
184    
185        /**
186         * Strings together a random number of word lists (in sentence form) to create something that looks like a
187         * paragraph.
188         *
189         * @param minSentences per paragraph
190         * @param maxSentences per paragraph
191         * @param minWords     per sentence
192         * @param maxWords     per sentence
193         * @return the random paragraph
194         */
195        public String paragraph(int minSentences, int maxSentences, int minWords, int maxWords)
196        {
197            assert minSentences < maxSentences;
198            assert minSentences > 0;
199    
200            int count = random(minSentences, maxSentences);
201    
202            StringBuilder builder = new StringBuilder();
203    
204            for (int i = 0; i < count; i++)
205            {
206                if (i > 0) builder.append(' ');
207    
208                builder.append(wordList(minWords, maxWords, true));
209            }
210    
211            return builder.toString();
212        }
213    }