package cz.moneta.test.harness.support.data;

import cz.moneta.test.harness.context.StoreAccessor;

/**
 * This is the marker interface of data builder proxies. These serve as simple dynamic sources of unique test data.
 * <p/>
 * Such data builders are usually accessed via {@code harness.data()} where the proxy is instantiated by calling
 * the respective {@link Builders#newDataBuilder(Class, StoreAccessor)} method.
 * <p/>
 * An example data builder may look as follows:
 * <pre>{@code
 * public interface AClient extends DataProvider<AClient>, StoreAccessor {
 *
 *    @literal @Generate(FIRST_NAME)
 *     String firstName();
 *
 *    @literal @Generate(LAST_NAME)
 *     String lastName();
 *
 *    @literal @Generate(RC)
 *     String birthNumber(LocalDate from, LocalDate to);
 *
 *    @literal @Value("Praha")
 *     String placeOfBirth();
 *
 *     default IdCard idCard(LocalDate dateOfBirth) {
 *         birthNumber(dateOfBirth, dateOfBirth);
 *         return generate(ID_CARD, dateOfBirth);
 *     }
 *
 *    @literal @Value("El123543")
 *     String driverLicenceId();
 *
 *    @literal @Persists
 *     default AClient withBesimRuleForGeneratedIco() {
 *         new BesimTasks(this).setupIco(this);
 *         return this;
 *     }
 *
 *     default Address residencyAddress() {
 *         return Address.builder()
 *                 .street("Pražská")
 *                 .descriptiveNumber("121")
 *                 .orientationNumber("")
 *                 .city("Kolín")
 *                 .zip("28002")
 *                 .country("CZ")
 *                 .build();
 *     }
 *
 *    @literal @Generate(MOBILE_PHONE_NUMBER)
 *     String mobileNumber();
 *
 *    @literal @Value("nothing@nothing.com")
 *     String email();
 *
 *     AClient withFirstName(String firstName);
 *
 *     AClient withLastName(String lastName);
 *
 *     AClient withBirthNumber(String birthNumber);
 *
 *     AClient withPlaceOfBirth(String placeOfBirth);
 *
 *     AClient withIdCard(IdCard idCard);
 *
 *     AClient withDriverLicenceId(String driverLicenceId);
 *
 *     AClient withResidencyAddress(Address residencyAddress);
 *
 *     AClient withMobileNumber(String mobileNumber);
 *
 *     AClient withEmail(String email);
 * }
 * }</pre>
 *
 * And the usage would be as follows:
 * <pre>{@code
 * AClient client = Builders.newDataBuilder(AClient.class, harness)
 *     // override the default email
 *     .withEmail("something@nothing.com")
 *     // use a specific name rather than a generated one
 *     .withFirstName("Rudolf")
 *
 *  // get a generated id card object
 *  IdCard idCard = client.idCard(LocalDate.of(2016, 1, 1));
 *  // get the place of birth
 *  String placeOfBirth = client.placeOfBirth();
 *  ...
 *
 * }</pre>
 *
 * Please note that data is generated only once and lazily (i.e. calling the {@code idCard} method always returns
 * the same instance of IdCard which, in turn, is only generated after the first call to the method)
 *
 * @see Generate
 * @see Value
 * @see Date
 * @see Persists
 */
public interface DataProvider<B extends DataProvider<B>> {
}
