/***************************************************************** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. ****************************************************************/ package org.apache.cayenne.datafactory; import java.util.Calendar; import java.util.Date; import java.util.Random; /** * @since 4.0 */ public class DataFactory { private Random random = ValueProvider.RANDOM; /** * @return A random first name */ public String getFirstName() { return ValueProvider.FIRST_NAMES.randomValue(); } /** * @return a combination of first and last name values in one string */ public String getName() { return getFirstName() + " " + getLastName(); } /** * @return A random last name */ public String getLastName() { return ValueProvider.LAST_NAMES.randomValue(); } /** * @return A random street name */ public String getStreetName() { return ValueProvider.STREET_NAMES.randomValue(); } /** * @return A random street suffix */ public String getStreetSuffix() { return ValueProvider.ADDRESS_SUFFIXES.randomValue(); } /** * @return City as a string */ public String getCity() { return ValueProvider.CITIES.randomValue(); } /** * Generates an address value consisting of house number, street name and * street suffix. i.e. <code>543 Larkhill Road</code> * * @return Address as a string */ public String getAddress() { int num = 404 + random.nextInt(1400); return num + " " + getStreetName() + " " + getStreetSuffix(); } /** * Generates line 2 for a street address (usually an Apt. or Suite #). * Returns default value if the probabilty test fails. * * @return Street address line 2 */ public String getAddressLine2() { int test = random.nextInt(100); if (test < 50) { return "Apt #" + 100 + random.nextInt(1000); } else { return "Suite #" + 100 + random.nextInt(1000); } } /** * Creates a random birthdate within the range of 1955 to 1985 * * @return Date representing a birthdate */ public Date getBirthDate() { Date base = new Date(0); return getDate(base, -365 * 15, 365 * 15); } /** * Returns a random int value. * * @return random number */ public int getNumber() { return getNumberBetween(Integer.MIN_VALUE, Integer.MAX_VALUE); } /** * Returns a random number between 0 and max * * @param max * Maximum value of result * @return random number no more than max */ public int getNumberUpTo(int max) { return getNumberBetween(0, max); } /** * Returns a number betwen min and max * * @param min * minimum value of result * @param max * maximum value of result * @return Random number within range */ public int getNumberBetween(int min, int max) { if (max < min) { throw new IllegalArgumentException(String.format( "Minimum must be less than minimum (min=%d, max=%d)", min, max)); } return min + random.nextInt(max - min); } /** * Builds a date from the year, month, day values passed in * * @param year * The year of the final {@link Date} result * @param month * The month of the final {@link Date} result (from 1-12) * @param day * The day of the final {@link Date} result * @return Date representing the passed in values. */ public Date getDate(int year, int month, int day) { Calendar cal = Calendar.getInstance(); cal.clear(); cal.set(year, month - 1, day, 0, 0, 0); return cal.getTime(); } /** * Returns a random date which is in the range <code>baseData</code> + * <code>minDaysFromData</code> to <code>baseData</code> + * <code>maxDaysFromData</code>. This method does not alter the time * component and the time is set to the time value of the base date. * * @param baseDate * Date to start from * @param minDaysFromDate * minimum number of days from the baseDate the result can be * @param maxDaysFromDate * maximum number of days from the baseDate the result can be * @return A random date */ public Date getDate(Date baseDate, int minDaysFromDate, int maxDaysFromDate) { Calendar cal = Calendar.getInstance(); cal.setTime(baseDate); int diff = minDaysFromDate + (random.nextInt(maxDaysFromDate - minDaysFromDate)); cal.add(Calendar.DATE, diff); return cal.getTime(); } /** * Returns a random date between two dates. This method will alter the time * component of the dates * * @param minDate * Minimum date that can be returned * @param maxDate * Maximum date that can be returned * @return random date between these two dates. */ public Date getDateBetween(Date minDate, Date maxDate) { // this can break if seconds is an int long seconds = (maxDate.getTime() - minDate.getTime()) / 1000; seconds = (long) (random.nextDouble() * seconds); Date result = new Date(); result.setTime(minDate.getTime() + (seconds * 1000)); return result; } /** * Returns random text made up of english words of length * <code>length</code> * * @param length * length of returned string * * @return string made up of actual words with length <code>length</code> */ public String getRandomText(int length) { return getRandomText(length, length); } /** * Returns random text made up of english words * * @param minLength * minimum length of returned string * @param maxLength * maximum length of returned string * @return string of length between min and max length */ public String getRandomText(int minLength, int maxLength) { validateMinMaxParams(minLength, maxLength); StringBuilder sb = new StringBuilder(maxLength); int length = minLength; if (maxLength != minLength) { length = length + random.nextInt(maxLength - minLength); } while (length > 0) { if (sb.length() != 0) { sb.append(" "); length--; } String word = getRandomWord(); sb.append(word); length = length - word.length(); } if (sb.length() < maxLength) { return sb.toString(); } else { return sb.substring(0, maxLength); } } private void validateMinMaxParams(int minLength, int maxLength) { if (minLength < 0) { throw new IllegalArgumentException("Minimum length must be a non-negative number"); } if (maxLength < 0) { throw new IllegalArgumentException("Maximum length must be a non-negative number"); } if (maxLength < minLength) { throw new IllegalArgumentException( String.format( "Minimum length must be less than maximum length (min=%d, max=%d)", minLength, maxLength)); } } /** * @return a random character */ public char getRandomChar() { return (char) (random.nextInt(26) + 'a'); } /** * Return a string containing <code>length</code> random characters * * @param length * number of characters to use in the string * @return A string containing <code>length</code> random characters */ public String getRandomChars(int length) { return getRandomChars(length, length); } /** * Return a string containing between <code>length</code> random characters * * @param maxLength max number of characters to use in the string * @param minLength min number of characters to use in the string * @return A string containing <code>length</code> random characters */ public String getRandomChars(int minLength, int maxLength) { validateMinMaxParams(minLength, maxLength); StringBuilder sb = new StringBuilder(maxLength); int length = minLength; if (maxLength != minLength) { length = length + random.nextInt(maxLength - minLength); } while (length > 0) { sb.append(getRandomChar()); length--; } return sb.toString(); } /** * Returns a word of a length between 1 and 10 characters. * * @return A work of max length 10 */ public String getRandomWord() { return ValueProvider.WORDS.randomValue(); } /** * * @param chance * Chance of a suffix being returned * @return */ public String getSuffix(int chance) { return ValueProvider.suffixes.randomValue(chance); } /** * Return a person prefix or null if the odds are too low. * * @param chance * Odds of a prefix being returned * @return Prefix string */ public String getPrefix(int chance) { return ValueProvider.prefixes.randomValue(chance); } /** * Returns a string containing a set of numbers with a fixed number of * digits * * @param digits * number of digits in the final number * @return Random number as a string with a fixed length */ public String getNumberText(int digits) { StringBuilder result = new StringBuilder(digits); for (int i = 0; i < digits; i++) { result.append(random.nextInt(10)); } return result.toString(); } /** * Generates an email address * * @return an email address */ public String getEmailAddress() { return getLogin() + "@" + ValueProvider.EMAIL_HOSTS.randomValue() + "." + ValueProvider.TLDS.randomValue(); } public String getLogin() { int test = random.nextInt(100); String login; if (test < 20) { login = getFirstName().charAt(0) + getLastName(); } else if (test < 40) { login = getFirstName() + "." + getLastName(); } else if (test < 45) { login = getFirstName() + "_" + getLastName(); } else if (test < 55) { login = getLastName(); } else { login = getRandomWord() + getRandomWord(); } if (random.nextInt(100) > 80) { login = login + random.nextInt(100); } return login; } public boolean chance(int chance) { return random.nextInt(100) < chance; } /** * Call randomize with a seed value to reset the random number generator. By * using the same seed over different tests, you will should get the same * results out for the same data generation calls. * * @param seed * Seed value to use to generate random numbers */ public void randomize(int seed) { random = new Random(seed); } }