Let say we have a Person, and Person.getAddress() returns an Address object, and Address.getCity() returns a String city that person lives in. We might use this PropertyAccess:
Code:
interface PersonProperties extends PropertyAccess<Person> {
@Path("address.city")
ValueProvider<Person, String> city();
}
In this case, we'll be able to use that ValueProvider to get and set the city of the address of the person as if we were writing these lines of code:
Code:
person.getAddress().getCity()
person.getAddress().setCity(...)
But what happens if the address is null? It can't magically know that you don't want that to be null, that you intend for it to have a non-null value, and it can't create a new Address object for you - in that case, what should getCity do? Even if we rebuild that (and this doesn't make sense to me) to return null, what can setCity do when the user types in a value, for example, in a grid?
There is no way for us to create those sub-objects in a consistent way - what if you need a StreetAddress subclass of the abstract Address class? What if Address is a RequestFactory proxy, and thus only an interface? What if you must use a non-default constructor to build Address? Any of these make it hard to generate code that builds your sub-objects for you.
If you want custom behavior in your ValueProvider, built a custom implementation of the interface. PropertyAccess is only for simple generated default behavior.
Code:
class PersonWithNullableAddressCityValueProvider
implements ValueProvider<Person, String> {
public String getValue(Person object) {
return object.getAddress() == null ? null : object.getAddress().getCity();
}
public void setValue(Person object, String value) {
if (person.getAddress() == null) {
person.setAddress(new Address());
}
person.getAddress().setCity(value);
}
}