diff --git a/src/main/java/io/codearte/jfairy/Bootstrap.java b/src/main/java/io/codearte/jfairy/Bootstrap.java index 0b6a2e0c..383efd8f 100644 --- a/src/main/java/io/codearte/jfairy/Bootstrap.java +++ b/src/main/java/io/codearte/jfairy/Bootstrap.java @@ -144,6 +144,8 @@ private static FairyModule getFairyModuleForLocale(DataMaster dataMaster, Locale return new SvFairyModule(dataMaster, random); case ZH: return new ZhFairyModule(dataMaster, random); + case DE: + return new DeFairyModule(dataMaster, random); default: LOG.info("No data for your language - using EN"); return new EnFairyModule(dataMaster, random); diff --git a/src/main/java/io/codearte/jfairy/DeFairyModule.java b/src/main/java/io/codearte/jfairy/DeFairyModule.java new file mode 100644 index 00000000..4994ca3b --- /dev/null +++ b/src/main/java/io/codearte/jfairy/DeFairyModule.java @@ -0,0 +1,36 @@ +package io.codearte.jfairy; + +import io.codearte.jfairy.data.DataMaster; +import io.codearte.jfairy.producer.VATIdentificationNumberProvider; +import io.codearte.jfairy.producer.company.locale.de.DeVATIdentificationNumberProvider; +import io.codearte.jfairy.producer.person.AddressProvider; +import io.codearte.jfairy.producer.person.NationalIdentificationNumberFactory; +import io.codearte.jfairy.producer.person.NationalIdentityCardNumberProvider; +import io.codearte.jfairy.producer.person.PassportNumberProvider; +import io.codearte.jfairy.producer.person.locale.NoNationalIdentificationNumberFactory; +import io.codearte.jfairy.producer.person.locale.de.DeAddressProvider; +import io.codearte.jfairy.producer.person.locale.de.DeNationalIdentityCardNumberProvider; +import io.codearte.jfairy.producer.person.locale.de.DePassportNumberProvider; + +import java.util.Random; + +/** + * @author Roland Weisleder + */ +public class DeFairyModule extends FairyModule { + + public DeFairyModule(DataMaster dataMaster, Random random) { + super(dataMaster, random); + } + + @Override + protected void configure() { + super.configure(); + bind(NationalIdentificationNumberFactory.class).to(NoNationalIdentificationNumberFactory.class); + bind(NationalIdentityCardNumberProvider.class).to(DeNationalIdentityCardNumberProvider.class); + bind(VATIdentificationNumberProvider.class).to(DeVATIdentificationNumberProvider.class); + bind(AddressProvider.class).to(DeAddressProvider.class); + bind(PassportNumberProvider.class).to(DePassportNumberProvider.class); + } + +} diff --git a/src/main/java/io/codearte/jfairy/producer/company/locale/de/DeVATIdentificationNumberProvider.java b/src/main/java/io/codearte/jfairy/producer/company/locale/de/DeVATIdentificationNumberProvider.java new file mode 100644 index 00000000..f82ffb3d --- /dev/null +++ b/src/main/java/io/codearte/jfairy/producer/company/locale/de/DeVATIdentificationNumberProvider.java @@ -0,0 +1,27 @@ +package io.codearte.jfairy.producer.company.locale.de; + +import io.codearte.jfairy.producer.VATIdentificationNumberProvider; + +import static org.apache.commons.lang3.RandomStringUtils.randomNumeric; + +/** + * German VAT identification number (Umsatzsteuer-Identifikationsnummer or USt-IdNr.) + *
+ * https://en.wikipedia.org/wiki/VAT_identification_number + * + * @author Roland Weisleder + */ +public class DeVATIdentificationNumberProvider implements VATIdentificationNumberProvider { + + private static final String VALID_NUMBER_PATTERN = "^[0-9]{9}$"; + + @Override + public String get() { + return randomNumeric(9); + } + + public boolean isValid(String vatIdentificationNumber) { + return vatIdentificationNumber.matches(VALID_NUMBER_PATTERN); + } + +} diff --git a/src/main/java/io/codearte/jfairy/producer/person/locale/de/DeAddress.java b/src/main/java/io/codearte/jfairy/producer/person/locale/de/DeAddress.java new file mode 100644 index 00000000..58fb8612 --- /dev/null +++ b/src/main/java/io/codearte/jfairy/producer/person/locale/de/DeAddress.java @@ -0,0 +1,65 @@ +package io.codearte.jfairy.producer.person.locale.de; + +import io.codearte.jfairy.producer.person.Address; + +import static org.apache.commons.lang3.StringUtils.isNotBlank; +import static org.apache.commons.lang3.SystemUtils.LINE_SEPARATOR; + +/** + * @author Roland Weisleder + */ +public class DeAddress implements Address { + + private final String streetNumber; + + private final String street; + + private final String apartmentNumber; + + private final String city; + + private final String postalCode; + + public DeAddress(String streetNumber, String street, String apartmentNumber, String city, String postalCode) { + this.streetNumber = streetNumber; + this.street = street; + this.apartmentNumber = apartmentNumber; + this.city = city; + this.postalCode = postalCode; + } + + public String getStreetNumber() { + return streetNumber; + } + + public String getStreet() { + return street; + } + + public String getApartmentNumber() { + return apartmentNumber; + } + + public String getCity() { + return city; + } + + public String getPostalCode() { + return postalCode; + } + + public String getAddressLine1() { + return street + " " + streetNumber + + (isNotBlank(apartmentNumber) ? ", " + apartmentNumber : ""); + } + + public String getAddressLine2() { + return postalCode + " " + city; + } + + @Override + public String toString() { + return getAddressLine1() + LINE_SEPARATOR + getAddressLine2(); + } + +} diff --git a/src/main/java/io/codearte/jfairy/producer/person/locale/de/DeAddressProvider.java b/src/main/java/io/codearte/jfairy/producer/person/locale/de/DeAddressProvider.java new file mode 100644 index 00000000..67fea3f4 --- /dev/null +++ b/src/main/java/io/codearte/jfairy/producer/person/locale/de/DeAddressProvider.java @@ -0,0 +1,25 @@ +package io.codearte.jfairy.producer.person.locale.de; + +import io.codearte.jfairy.data.DataMaster; +import io.codearte.jfairy.producer.BaseProducer; +import io.codearte.jfairy.producer.person.AbstractAddressProvider; + +import javax.inject.Inject; + +/** + * @author Roland Weisleder + */ +public class DeAddressProvider extends AbstractAddressProvider { + + @Inject + public DeAddressProvider(DataMaster dataMaster, BaseProducer baseProducer) { + super(dataMaster, baseProducer); + } + + @Override + public DeAddress get() { + return new DeAddress(getStreetNumber(), getStreet(), getApartmentNumber(), + getCity(), getPostalCode()); + } + +} diff --git a/src/main/java/io/codearte/jfairy/producer/person/locale/de/DeNationalIdentityCardNumberProvider.java b/src/main/java/io/codearte/jfairy/producer/person/locale/de/DeNationalIdentityCardNumberProvider.java new file mode 100644 index 00000000..f93d84dd --- /dev/null +++ b/src/main/java/io/codearte/jfairy/producer/person/locale/de/DeNationalIdentityCardNumberProvider.java @@ -0,0 +1,39 @@ +package io.codearte.jfairy.producer.person.locale.de; + +import io.codearte.jfairy.producer.BaseProducer; +import io.codearte.jfairy.producer.person.NationalIdentityCardNumberProvider; + +import javax.inject.Inject; + +import static org.apache.commons.lang3.RandomStringUtils.randomNumeric; + +/** + * German Identity Card (known as Personalausweis) + *
+ * https://en.wikipedia.org/wiki/German_identity_card + * + * @author Roland Weisleder + */ +public class DeNationalIdentityCardNumberProvider implements NationalIdentityCardNumberProvider { + + private static final String[] ID_CARD_TYPE_LETTERS = {"L", "M", "N", "P", "R", "T", "V", "W", "X", "Y"}; + + private static final String VALID_NUMBER_PATTERN = "^[LMNPRTVWXY][0-9]{8}$"; + + private final BaseProducer baseProducer; + + @Inject + public DeNationalIdentityCardNumberProvider(BaseProducer baseProducer) { + this.baseProducer = baseProducer; + } + + @Override + public String get() { + return baseProducer.randomElement(ID_CARD_TYPE_LETTERS) + randomNumeric(8); + } + + public boolean isValid(String nationalIdentityCardNumber) { + return nationalIdentityCardNumber.matches(VALID_NUMBER_PATTERN); + } + +} diff --git a/src/main/java/io/codearte/jfairy/producer/person/locale/de/DePassportNumberProvider.java b/src/main/java/io/codearte/jfairy/producer/person/locale/de/DePassportNumberProvider.java new file mode 100644 index 00000000..75911d6b --- /dev/null +++ b/src/main/java/io/codearte/jfairy/producer/person/locale/de/DePassportNumberProvider.java @@ -0,0 +1,39 @@ +package io.codearte.jfairy.producer.person.locale.de; + +import io.codearte.jfairy.producer.BaseProducer; +import io.codearte.jfairy.producer.person.PassportNumberProvider; + +import javax.inject.Inject; + +import static org.apache.commons.lang3.RandomStringUtils.randomNumeric; + +/** + * German passport (known as Reisepass) + *
+ * https://en.wikipedia.org/wiki/German_passport + * + * @author Roland Weisleder + */ +public class DePassportNumberProvider implements PassportNumberProvider { + + private static final String[] PASSPORT_TYPE_LETTERS = {"C", "F", "G", "H", "J", "K"}; + + private static final String VALID_NUMBER_PATTERN = "^[CFGHJK][0-9]{8}$"; + + private final BaseProducer baseProducer; + + @Inject + public DePassportNumberProvider(BaseProducer baseProducer) { + this.baseProducer = baseProducer; + } + + @Override + public String get() { + return baseProducer.randomElement(PASSPORT_TYPE_LETTERS) + randomNumeric(8); + } + + public boolean isValid(String passportNumber) { + return passportNumber.matches(VALID_NUMBER_PATTERN); + } + +} diff --git a/src/test/groovy/io/codearte/jfairy/FairyDeSpec.groovy b/src/test/groovy/io/codearte/jfairy/FairyDeSpec.groovy new file mode 100644 index 00000000..ff6c8cd7 --- /dev/null +++ b/src/test/groovy/io/codearte/jfairy/FairyDeSpec.groovy @@ -0,0 +1,28 @@ +package io.codearte.jfairy + +import io.codearte.jfairy.producer.person.Person +import spock.lang.Specification + +/** + * @author Roland Weisleder + */ +class FairyDeSpec extends Specification { + + private final int SEED = 186 + private Fairy fairy = Fairy.builder().withRandom(new Random(SEED)).withLocale(Locale.GERMAN).build() + + def "Should create German name"() { + when: + Person person = fairy.person(); + then: + person.fullName == 'Horstfried Scheidt' // well, that's german enough... + } + + def "Should create German city"() { + when: + Person person = fairy.person(); + then: + person.address.city == 'Oberursel Taunus' + } + +} diff --git a/src/test/groovy/io/codearte/jfairy/producer/company/locale/de/DeVATIdentificationNumberProviderSpec.groovy b/src/test/groovy/io/codearte/jfairy/producer/company/locale/de/DeVATIdentificationNumberProviderSpec.groovy new file mode 100644 index 00000000..1b48d692 --- /dev/null +++ b/src/test/groovy/io/codearte/jfairy/producer/company/locale/de/DeVATIdentificationNumberProviderSpec.groovy @@ -0,0 +1,32 @@ +package io.codearte.jfairy.producer.company.locale.de + +import spock.lang.Specification +import spock.lang.Unroll + +/** + * @author Roland Weisleder + */ +class DeVATIdentificationNumberProviderSpec extends Specification { + + private DeVATIdentificationNumberProvider generator = new DeVATIdentificationNumberProvider() + + @Unroll + def "Should validate #vatIdentificationNumber as #valid"() { + expect: + generator.isValid(vatIdentificationNumber) == valid + where: + vatIdentificationNumber | valid + '999999999' | true + '1234567890' | false + '000000000' | true + '18947440810' | false + } + + def "Should always generate proper vatIdentificationNumber"() { + expect: + generator.isValid(generator.get()) + where: + i << (1..100) + } + +} diff --git a/src/test/groovy/io/codearte/jfairy/producer/person/locale/de/DeAddressSpec.groovy b/src/test/groovy/io/codearte/jfairy/producer/person/locale/de/DeAddressSpec.groovy new file mode 100644 index 00000000..39ed3106 --- /dev/null +++ b/src/test/groovy/io/codearte/jfairy/producer/person/locale/de/DeAddressSpec.groovy @@ -0,0 +1,60 @@ +package io.codearte.jfairy.producer.person.locale.de + +import io.codearte.jfairy.Fairy +import io.codearte.jfairy.producer.person.Address +import spock.lang.Specification + +import static org.apache.commons.lang3.SystemUtils.LINE_SEPARATOR + +class DeAddressSpec extends Specification { + + private final int SEED = 7 + private Fairy fairy; + private Address address + + def setup() { + fairy = Fairy.builder().withRandom(new Random(SEED)).withLocale(Locale.GERMAN).build() + address = fairy.person().address + } + + def "should generate random street"() { + expect: + address.street == 'Messelweg' + } + + def "should generate random streetNumber"() { + expect: + address.streetNumber == '176' + } + + def "should generate random apartmentNumber"() { + expect: + address.apartmentNumber == '' + } + + def "should generate random postalCode"() { + expect: + address.postalCode == '15286' + } + + def "should generate random city"() { + expect: + address.city == 'Schlitz' + } + + def "should return addressLine1 in de locale format"() { + expect: + address.addressLine1 == 'Messelweg 176' + } + + def "should return addressLine2 in de locale format"() { + expect: + address.addressLine2 == '15286 Schlitz' + } + + def "should return address in de locale format"() { + expect: + address.toString() == "Messelweg 176${LINE_SEPARATOR}15286 Schlitz" + } + +} diff --git a/src/test/groovy/io/codearte/jfairy/producer/person/locale/de/DeNationalIdentityCardNumberProviderSpec.groovy b/src/test/groovy/io/codearte/jfairy/producer/person/locale/de/DeNationalIdentityCardNumberProviderSpec.groovy new file mode 100644 index 00000000..62e8f8f5 --- /dev/null +++ b/src/test/groovy/io/codearte/jfairy/producer/person/locale/de/DeNationalIdentityCardNumberProviderSpec.groovy @@ -0,0 +1,34 @@ +package io.codearte.jfairy.producer.person.locale.de + +import io.codearte.jfairy.producer.BaseProducer +import spock.lang.Specification +import spock.lang.Unroll + +/** + * @author Roland Weisleder + */ +class DeNationalIdentityCardNumberProviderSpec extends Specification { + + private BaseProducer baseProducer = new BaseProducer(new Random()) + private DeNationalIdentityCardNumberProvider generator = new DeNationalIdentityCardNumberProvider(baseProducer) + + @Unroll + def "Should validate #nationalIdentityCardNumber as #valid"() { + expect: + generator.isValid(nationalIdentityCardNumber) == valid + where: + nationalIdentityCardNumber | valid + 'T22000129' | true + '123456789' | false + 'L00000000' | true + 'A12345678' | false + } + + def "Should always generate proper nationalIdentityCardNumber"() { + expect: + generator.isValid(generator.get()) + where: + i << (1..100) + } + +} diff --git a/src/test/groovy/io/codearte/jfairy/producer/person/locale/de/DePassportNumberProviderSpec.groovy b/src/test/groovy/io/codearte/jfairy/producer/person/locale/de/DePassportNumberProviderSpec.groovy new file mode 100644 index 00000000..5a2ceb5d --- /dev/null +++ b/src/test/groovy/io/codearte/jfairy/producer/person/locale/de/DePassportNumberProviderSpec.groovy @@ -0,0 +1,34 @@ +package io.codearte.jfairy.producer.person.locale.de + +import io.codearte.jfairy.producer.BaseProducer +import spock.lang.Specification +import spock.lang.Unroll + +/** + * @author Roland Weisleder + */ +class DePassportNumberProviderSpec extends Specification { + + private BaseProducer baseProducer = new BaseProducer(new Random()) + private DePassportNumberProvider generator = new DePassportNumberProvider(baseProducer) + + @Unroll + def "Should validate #passportNumber as #valid"() { + expect: + generator.isValid(passportNumber) == valid + where: + passportNumber | valid + 'C22000129' | true + '123456789' | false + 'H00000000' | true + 'A12345678' | false + } + + def "Should always generate proper passportNumber"() { + expect: + generator.isValid(generator.get()) + where: + i << (1..100) + } + +}