/phantom-pojos

Immutable value types and builders implemented with dynamic proxies.

Primary LanguageJavaApache License 2.0Apache-2.0

phantom-pojos

Build Status

Immutable value types and builders implemented with dynamic proxies.

An PhantomPojo is a bean-like object defined using two interfaces:

public interface Person extends PhantomPojo<Person.Builder> {

    interface Builder extends Supplier<Person> {
        Builder withName(String name);
        Builder withAge(int age);
        Builder withFriends(Builder...friendBuilders);
        Builder withAddress(Address.Builder addressBuilder);
    }

    static Builder builder() {
        return PhantomBuilder.building(Person.class);
    }

    String getName();
    int getAge();
    List<Person> getFriends();
    Address getAddress();
}

Implementations of these interfaces are automatically created by PhantomBuilder (using dynamic proxies). They implement equals, hashCode and toString.

You create an instance of a PhantomPojo with its Builder, like so:

Person henry = Person.builder()
                .withName("Henry")
                .withAge(42)
                .withFriends(Person.builder()
                    .withName("Jerry")
                    .withAge(33)
                    .withFriends())
                .get();

The created object has getter methods for each of its properties:

assertThat(henry.getName(), equalTo("Henry"));
assertThat(henry.getFriends().get(0).getAge(), equalTo(33));

Once it has been created it cannot be changed, but a modified copy can be created using the update method:

Person henrietta = henry.update().withName("Henrietta").get();

A PhantomPojo wraps an array of property values, and can be created directly out of a map of property names to property values:

Map<String, Object> properties = new HashMap<>();
properties.put("name", "Angie");
properties.put("age", 63);
Person angie = PhantomPojo.wrapping(properties).with(Person.class);

assertThat(angie.getAge(), equalTo(63));

You can always retrieve this map of property values from the PhantomPojo via its properties method:

assertThat(angie.properties().get("name"), equalTo("Angie"));

Nested maps are automatically promoted to PhantomPojos:

Map<String, Object> addressProperties = new HashMap<>();
addressProperties.put("addressLines", Arrays.asList("67 Penguin Street", "Cinderford"));
addressProperties.put("postcode", "RA8 81T");

Map<String, Object> personProperties = new HashMap<>();
personProperties.put("name", "Harry");
personProperties.put("age", 37);
personProperties.put("address", addressProperties);

Person person = PhantomPojo.wrapping(personProperties).with(Person.class);

assertThat(person.getAddress().getPostcode(), equalTo("RA8 81T"));