The get(...)
method takes a Question and evaluates it.
Questions have a bunch of "modern" chainable methods like:
refineWith(Question q)
or then(Question q)
or(Question)
andorAsk(Question q)
andorAsk(otherSubject, Question q)
for a matching answer typeorDefaultTo(answer)
in case of exceptions or null
@Test
public void useTheAlternativeWhenItThrows() {
Person bob = new Person("Bob", "Sinclair");
assertThat(bob.get(throwingQuestion().orAsk(lastName())), is("Sinclair"));
}
@Test
public void alternativeQuestionsAreLazy() {
Person bob = new Person("Bob", "Sinclair");
assertThat(bob.get(firstName().orAsk(throwingQuestion())), is("Bob"));
}
@Test
public void alternativeQuestionOfDifferentSubject() {
Person bob = new Person("Bob", "Sinclair");
Address address = new Address("Old Street");
assertThat(bob.get(lastName().orAsk(address, streetName())), is("Sinclair"));
}
@Test
public void stillARegularQuestion() {
Person bob = new Person(null, null);
Question<Person, String> anyName = firstName().or(lastName()).orDefaultTo("Pablo");
assertThat(bob.get(anyName), is("Pablo"));
}
private Question<Person, String> throwingQuestion() {
return new Question<Person, String>() {
@Override
public Answer<String> answer() {
throw new RuntimeException("💥");
}
};
}
public Question<Person, String> firstName() {
return new Question<Person, String>() {
@Override
public Answer<String> answer() {
return Answer.with(subject.firstName);
}
};
}
public Question<Person, String> lastName() {
return new Question<Person, String>() {
@Override
public Answer<String> answer() {
return Answer.with(subject.lastName);
}
};
}
public Question<Address, String> streetName() {
return new Question<Address, String>() {
@Override
public Answer<String> answer() {
return Answer.with(subject.street);
}
};
}
public class Person extends AcceptsQuestions<Person> {
private final String firstName;
private final String lastName;
public Person(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
}
public class Address extends AcceptsQuestions<Address> {
private final String street;
public Address(String street) {
this.street = street;
}
}