// Path: core/src/test/java/eventsrc4j/sample/person/PersonName.java
// public static Option<NameValue> parseName(String value) {
//   return !value.trim().isEmpty()
//       && !value.endsWith(" ")
//       && !value.startsWith(" ")
//       && value.length() <= 120
// 
//       ? some(NameValue0(value))
//       : Option.<NameValue>none();
// }


import fj.F;
import fj.Unit;
import fj.data.List;
import fj.data.NonEmptyList;
import fj.data.Option;
import fj.data.Validation;
import static eventsrc4j.sample.person.Addresses.Address;
import static eventsrc4j.sample.person.Addresses.modNumber;
import static eventsrc4j.sample.person.Contacts.getPostalAddress;
import static eventsrc4j.sample.person.Contacts.modPostalAddress;
import static eventsrc4j.sample.person.FirstNames.FirstName;
import static eventsrc4j.sample.person.LastNames.LastName;
import static eventsrc4j.sample.person.NameValues.NameValue0;
import static eventsrc4j.sample.person.PersonName.NameValue.parseName;
import static eventsrc4j.sample.person.PersonNames.PersonName;
import static eventsrc4j.sample.person.Persons.Person;
import static eventsrc4j.sample.person.Persons.getContact;
import static eventsrc4j.sample.person.Persons.modContact;
import static fj.Semigroup.nonEmptyListSemigroup;
import static fj.Unit.unit;
import static fj.data.Option.none;
import static fj.data.Option.some;
import static fj.data.Option.some_;
import static fj.data.Validation.success;
            LastName(NameValue0("Black"))
        ),
        Contacts.byMail(
            Address(10, "Main St")
        ),
        none()
    ));
  }

  private static Validation<NonEmptyList<String>, PersonName> validatePersonName(
      String stringFirstName, Option<String> stringMiddleName, String stringLastName) {

    return
        // validate first name
        validateName(stringFirstName, "First name").map(FirstNames::FirstName).nel()
            .accumulate(nonEmptyListSemigroup(),

            // validate middle name if present
            stringMiddleName.map(s -> validateName(s, "Middle Name").map(MiddleNames::MiddleName).map(some_()))
                .orSome(Validation.success(none())).nel(),

            // validate last name
            validateName(stringLastName, "Last name").map(LastNames::LastName).nel(),

            // assemble all
            PersonNames::PersonName
        );
  }

  public static Validation<String, PersonName.NameValue> validateName(String name, String format) {
// Path: core/src/test/java/eventsrc4j/sample/person/PersonName.java
// public static Option<NameValue> parseName(String value) {
//   return !value.trim().isEmpty()
//       && !value.endsWith(" ")
//       && !value.startsWith(" ")
//       && value.length() <= 120
// 
//       ? some(NameValue0(value))
//       : Option.<NameValue>none();
// }


// Path: core/src/test/java/eventsrc4j/sample/person/PersonService.java
import fj.F;
import fj.Unit;
import fj.data.List;
import fj.data.NonEmptyList;
import fj.data.Option;
import fj.data.Validation;
import static eventsrc4j.sample.person.Addresses.Address;
import static eventsrc4j.sample.person.Addresses.modNumber;
import static eventsrc4j.sample.person.Contacts.getPostalAddress;
import static eventsrc4j.sample.person.Contacts.modPostalAddress;
import static eventsrc4j.sample.person.FirstNames.FirstName;
import static eventsrc4j.sample.person.LastNames.LastName;
import static eventsrc4j.sample.person.NameValues.NameValue0;
import static eventsrc4j.sample.person.PersonName.NameValue.parseName;
import static eventsrc4j.sample.person.PersonNames.PersonName;
import static eventsrc4j.sample.person.Persons.Person;
import static eventsrc4j.sample.person.Persons.getContact;
import static eventsrc4j.sample.person.Persons.modContact;
import static fj.Semigroup.nonEmptyListSemigroup;
import static fj.Unit.unit;
import static fj.data.Option.none;
import static fj.data.Option.some;
import static fj.data.Option.some_;
import static fj.data.Validation.success;

            LastName(NameValue0("Black"))
        ),
        Contacts.byMail(
            Address(10, "Main St")
        ),
        none()
    ));
  }

  private static Validation<NonEmptyList<String>, PersonName> validatePersonName(
      String stringFirstName, Option<String> stringMiddleName, String stringLastName) {

    return
        // validate first name
        validateName(stringFirstName, "First name").map(FirstNames::FirstName).nel()
            .accumulate(nonEmptyListSemigroup(),

            // validate middle name if present
            stringMiddleName.map(s -> validateName(s, "Middle Name").map(MiddleNames::MiddleName).map(some_()))
                .orSome(Validation.success(none())).nel(),

            // validate last name
            validateName(stringLastName, "Last name").map(LastNames::LastName).nel(),

            // assemble all
            PersonNames::PersonName
        );
  }

  public static Validation<String, PersonName.NameValue> validateName(String name, String format) {
    return parseName(name).toValidation(format + " is not valid");