Atom Feed SITE FEED   ADD TO GOOGLE READER

Coding in the small with Google Collections: Constraints.constrainedList

Part 8 in a Series.

Constraints.constrainedList allows you to enforce rules about what can be added to a List instance. By letting the List manage its constraints, your API users get instant feedback if they insert invalid values. It also allows you to expose convenient methods like addAll() and set() without writing additional code:

Before:

  private final List<LineItem> purchases = new ArrayList<LineItem>();

/**
* Don't modify this! Instead, call {@link #addPurchase(LineItem)} to add
* new purchases to this order.
*/
public List<LineItem> getPurchases() {
return Collections.unmodifiableList(purchases);
}

public void addPurchase(LineItem purchase) {
Preconditions.checkState(catalog.isOffered(getAddress(), purchase.getProduct()));
Preconditions.checkState(purchase.getCharge().getUnits() > 0);
purchases.add(purchase);
}

...

public static Order createGreyCupSpecialOrder(Customer customer) {
Order order = new Order(customer);
for (LineItem lineItem : GREY_CUP_SPECIAL_ITEMS) {
order.addPurchase(lineItem);
}
return order;
}


After:

  private final List<LineItem> purchases = Constraints.constrainedList(
new ArrayList<LineItem>(),
new Constraint<LineItem>() {
public void checkElement(LineItem element) {
Preconditions.checkState(catalog.isOffered(getAddress(), element.getProduct()));
Preconditions.checkState(element.getCharge().getUnits() > 0);
}
});

/**
* Returns the modifiable list of purchases in this order.
*/
public List<LineItem> getPurchases() {
return purchases;
}

...

public static Order createGreyCupSpecialOrder(Customer customer) {
Order order = new Order(customer);
order.getPurchases().addAll(GREY_CUP_SPECIAL_ITEMS);
return order;
}


This new code is both more robust and more convenient. Possibly the most common constraint, NOT_NULL is provided to make that easy. And as a special treat, there's constraint factory methods for Sets, Maps and the supplementary collections.

Part 9
Your link for Constraints.ConstrainList is broken. Also, I couldn't find the Constraints class in the 1.0RC1 docs ( maybe they are going to deprecate? )
Unfortunately for this post, ConstrainedList has been removed from Google Collections.

It turns out in practice that many people don't use ConstrainedLists. If you'd like it, please let the Google Collections team know.
So what would the recommended method be for this example now that the ConstrainedList class is gone?
Maybe a ForwardedList that does the appropriate guarding in the required methods?