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 }