package io.codearte.jfairy;
import com.google.common.base.Optional;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Provider;
import io.codearte.jfairy.data.DataMaster;
import io.codearte.jfairy.data.DataMasterModule;
import io.codearte.jfairy.data.MapBasedDataMaster;
import io.codearte.jfairy.producer.util.LanguageCode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.util.Locale;
import java.util.Random;
/**
* <p>Using a {@link #builder()}, you can configure the following fields:</p>
* <ul>
* <li><tt>locale</tt>: Specifies the locale for the random data file.</li>
* <li><tt>filePrefix</tt>: Specifies the file prefix.
* (So if you specify "jfairy" here and English for Locale, the data file will be
* "jfairy_en.yml" under the classpath.)
* </li>
* <li><tt>random</tt>: The Random object to use.</li>
* <li><tt>randomSeed</tt>: A specific random seed to use. Use this if you want the resulting
* data to be <strong>deterministic</strong> based on it, such as if you want the same test
* ID in a database to always result in the same fake name.
* </li>
* </ul>
* Obviously, don't set both <tt>random</tt> and <tt>randomSeed</tt>, only the last one you set will
* actually take effect.
*
* @author Jakub Kubrynski
* @author Olga Maciaszek-Sharma
*/
public class Bootstrap {
private static final Logger LOG = LoggerFactory.getLogger(Bootstrap.class);
private static final String DATA_FILE_PREFIX = "jfairy";
public static Fairy createFairy(DataMaster dataMaster, Locale locale, Random random) {
FairyModule fairyModule = getFairyModuleForLocale(dataMaster, locale, random);
Injector injector = Guice.createInjector(fairyModule);
FairyFactory fairyFactory = injector.getInstance(FairyFactory.class);
return fairyFactory.createFairy();
}
private static void fillDefaultDataMaster(MapBasedDataMaster dataMaster, Locale locale, String filePrefix) {
try {
dataMaster.readResources(filePrefix + ".yml");
dataMaster.readResources(filePrefix + "_" + locale.getLanguage() + ".yml");
} catch (IOException e) {
throw new IllegalStateException(e);
}
}
/**
* Creates a Builder that will let you configure a Fairy's fields one by one.
*
* @return a Builder instance.
*/
public static Builder builder() {
return new Builder();
}
/**
* Use this factory method to create dataset containing default jfairy.yml and jfairy_{langCode}.yml files
* merged with custom files with the same name
*
* @return Fairy instance
*/
public static Fairy create() {
return builder().build();
}
/**
* Use this factory method to create dataset containing default jfairy.yml and jfairy_{langCode}.yml files
* merged with custom files with the same name
*
* @param locale will be used to assess langCode for data file
* @return Fairy instance
*/
public static Fairy create(Locale locale) {
return builder().withLocale(locale).build();
}
/**
* Use this factory method to create your own dataset overriding bundled one
*
* @param locale will be used to assess langCode for data file
* @param dataFilePrefix prefix of the data file - final pattern will be jfairy.yml and dataFilePrefix_{langCode}.yml
* @return Fairy instance
*/
public static Fairy create(Locale locale, String dataFilePrefix) {
return builder().withLocale(locale)
.withFilePrefix(dataFilePrefix)
.build();
}
public static Fairy create(Provider<DataMaster> dataMaster, Locale locale) {
return builder().withDataMasterProvider(dataMaster).withLocale(locale).build();
}
/**
* Support customized language config
* @param dataMaster master of the config
* @param locale The Locale to set.
* @param random specific random
* @return FariyModule instance in accordance with locale
*/
private static FairyModule getFairyModuleForLocale(DataMaster dataMaster, Locale locale, Random random) {
LanguageCode code = null;
try {
code = LanguageCode.valueOf(locale.getLanguage().toUpperCase());
} catch (IllegalArgumentException e) {
LOG.warn("Uknown locale " + locale);
code = LanguageCode.EN;
}
switch (code) {
case PL:
return new PlFairyModule(dataMaster, random);
case EN:
return new EnFairyModule(dataMaster, random);
case ES:
return new EsFairyModule(dataMaster, random);
case FR:
return new EsFairyModule(dataMaster, random);
case SV:
return new SvFairyModule(dataMaster, random);
case ZH:
return new ZhFairyModule(dataMaster, random);
default:
LOG.info("No data for your language - using EN");
return new EnFairyModule(dataMaster, random);
}
}
public static class Builder {
private Locale locale = Locale.ENGLISH;
private String filePrefix = DATA_FILE_PREFIX;
private Random random = new Random();
private DataMaster dataMaster;
private MapBasedDataMaster getDefaultDataMaster() {
Injector injector = Guice.createInjector(new DataMasterModule(random));
return injector.getInstance(MapBasedDataMaster.class);
}
private Builder() {
}
/**
* Sets the locale for the resulting Fairy.
*
* @param locale The Locale to set.
* @return the same Builder (for chaining).
*/
public Builder withLocale(Locale locale) {
this.locale = locale;
return this;
}
/**
* Sets the data file prefix for the resulting Fairy.
*
* @param filePrefix The prefix of the file (such as "jfairy" for "jfairy_en.yml").
* @return the same Builder (for chaining).
*/
public Builder withFilePrefix(String filePrefix) {
this.filePrefix = filePrefix;
return this;
}
/**
* Sets the Random object to use to pick things randomly.
*
* @param random The Random to use.
* @return the same Builder (for chaining).
*/
public Builder withRandom(Random random) {
this.random = random;
return this;
}
/**
* Sets the random seed to use to pick things randomly. (If you set this, you will always
* get the same result when you generate things.)
*
* @param randomSeed The random seed to use.
* @return the same Builder (for chaining).
*/
public Builder withRandomSeed(long randomSeed) {
this.random = new Random(randomSeed);
return this;
}
/**
* Sets a custom DataMaster implementation.
*
* @param dataMasterProvider The random seed to use.
* @return the same Builder (for chaining).
*/
public Builder withDataMasterProvider(Provider<DataMaster> dataMasterProvider) {
this.dataMaster = dataMasterProvider.get();
return this;
}
/**
* Returns the completed Fairy.
*
* @return Fairy instance
*/
public Fairy build() {
if (dataMaster == null) {
dataMaster = getDefaultDataMaster();
fillDefaultDataMaster((MapBasedDataMaster) dataMaster, locale, filePrefix);
}
return createFairy(dataMaster, locale, random);
}
}
}