Pojomatic 1.0 API

Pojomatic is a library which allows simple implementation of the three methods Object.equals(Object), Object.hashCode() and Object.toString() by annotating properties on a Plain Old Java Object, or POJO.

See:
          Description

Packages
org.pojomatic Core Pojomatic classes.
org.pojomatic.annotations Annotations and enums to control the behavior of Pojomatic.
org.pojomatic.diff API and implementation classes to support Pojomatic.diff
org.pojomatic.formatter API and classes to help control the format used by Pojomatic.toString(Object) Pojomatic.toString}
org.pojomatic.internal The classes in this package are intended for internal use only.

 

Pojomatic is a library which allows simple implementation of the three methods Object.equals(Object), Object.hashCode() and Object.toString() by annotating properties on a Plain Old Java Object, or POJO. There are two steps to "pojomate" a POJO class: annotating, and implementing the three methods.

Annotations

Pojomatic behavior is controlled by annotations; these can be on a property-by-property basis, a class-wide basis, or a mix of the two. Class wide behavior can be controlled by the AutoProperty and PojoFormat, while property-specific behavior can be controlled by the Property and PropertyFormat annotations. A recommended practice is to provide an AutoProperty annotation at the class level, and then override the behavior it specifies on a per-property basis as needed. This minimizes both the number of annotations needed, as well as the number of additional steps needed when adding new properties to a class.

The annotations OverridesEquals and SubclassCannotOverrideEquals can be used to control the behavior of equals for inheritance hierarchies. If instances of a child class cannot possibly be equal to instances of the parent class which are not themselves instance of the child class, annotating the child class with OverridesEquals can inform Pojomatic of this (although if any additional properties have been added for inclusion in the equals method by the child class, Pojomatic will infer this automatically). Conversely, one can declare via the SubclassCannotOverrideEquals annotation that no additional properties will be added by child classes.

Implementing equals, hashCode and toString

To implement equals, hashCode and toString, simply annotate the class for pojomation (see below), and delegate to the static methods in Pojomatic:

  @Override public int hashCode() {
    return Pojomatic.hashCode(this);
  }

  @Override public String toString() {
    return Pojomatic.toString(this);
  }

  @Override public boolean equals(Object o) {
    return Pojomatic.equals(this, o);
  }

Implementing equals, hashCode and toString for interfaces

To implement equals, hashCode and toString for an interface, first annotate the interface for pojomation (see below) and define a static constant POJOMATOR in the interface:

import org.pojomatic.annotations.AutoProperty;
import org.pojomatic.Pojomator;
import org.pojomatic.Pojomatic;

@AutoProperty
public interface Interface {
  static Pojomator<Interface> POJOMATOR = Pojomatic.pojomator(Interface.class);
  ...
}

and then delegate to POJOMATOR in the implementing classes:

public class Implementation implements Interface {
  @Override public int hashCode() {
    return POJOMATOR.doHashCode(this);
  }

  @Override public boolean equals(Object other) {
    return POJOMATOR.doEquals(this, other);
  }

  @Override public String toString() {
    return POJOMATOR.doToString(this);
  }
  ...
}

Example Annotations

The simplest way to annotate a class for pojomation is to add a single AutoProperty annotation:

@AutoProperty //all fields are included by default
public class Common {
  ...
}

If you wish reference properties by getter methods instead of direct field access, you can do this by passing autoDetect=AutoDetectPolicy.METHOD to the AutoProperty annotation. By default, all properties are used in the implementations of the equals, hashCode and toString methods; this can be changed via the policy parameter to AutoProperty. Additionally, one can override this choice on a per-property basis by use of the Property annotation. For example, if you have a class with a mutable field which you do not wish to include in the hashCode calculation, you can accomplish this via:

@AutoProperty
public class Employee {
  private final String firstName;
  private final String lastName;

  @Property(policy=PojomaticPolicy.EQUALS_TO_STRING)
  private String securityLevel;
  ...
}

The toString implementation provided by Pojomatic defaults to using DefaultPojoFormatter; you can specify your own formatting by providing an alternate implementation of PojoFormatter and using the PojoFormat annotation. In addition to controlling the overall format of toString, the formatting of individual properties can be controlled by a PropertyFormat annotation referencing an implementation of PropertyFormatter. In addition to DefaultPropertyFormatter, this library also provides an AccountNumberFormatter for formatting properties with sensitive data. Taking all of this together, a Customer POJO using pojomatic might look like:

@AutoProperty
public class Customer {
  private final String firstName;

  private final String lastName;

  @PropertyFormat(AccountNumberFormatter.class)
  private final String accountNumber;

  public Customer(String accountNumber, String firstName, String lastName) {
    this.accountNumber = accountNumber;
    this.firstName = firstName;
    this.lastName = lastName;
  }

  public String getFirstName() { return firstName; }
  public String getLastName() { return lastName; }
  public String getAccountNumber() { return accountNumber; }

  @Override public int hashCode() {
    return Pojomatic.hashCode(this);
  }

  @Override public String toString() {
    return Pojomatic.toString(this);
  }

  @Override public boolean equals(Object o) {
    return Pojomatic.equals(this, o);
  }
}



Copyright © 2008-2010. All Rights Reserved.