Decorate an existing Map with
PredicatedMap from Commons Collections. Predicates add an inbound validation to a
Map, validating keys or values any
time an entry is added to a PredicatedMap. If a Predicate assigned to a key or value returns
false, put() throws an IllegalArgumentException. The following
example decorates a HashMap with
PredicatedMap—two Predicates are created to validate the keys
and the values:
import java.util.*;
import org.apache.commons.collections.map.PredicatedMap;
import org.apache.commons.collections.Predicate;
import org.apache.commons.collections.functors.EqualPredicate;
import org.apache.commons.collections.functors.InstanceofPredicate;
import org.apache.commons.collections.functors.OrPredicate;
// Create a Predicate that only accepts Strings
Predicate onlyStrings = new InstanceofPredicate( String.class );
// Create a Predicate that only allows "green" or "red"
Predicate onlyGreen = new EqualPredicate( "green" );
Predicate onlyRed = new EqualPredicate( "red" );
Predicate greenOrRed = new OrPredicate( onlyGreen, onlyRed );
// Created a Decorated Map - accepting String keys and "green" or "red" values
Map map = PredicatedMap.decorate( new HashMap( ), onlyStrings, greenOrRed );
// All of these puts should work
map.put( "tony" , "green" );
map.put( "alice" , "red" );
map.put( "mike" , "red" );
map.put( "bobby" , "green" );
// All of these puts should throw an IllegalArgumentException
map.put( new Double(4.0) , "green" );
map.put( "alice" , "purple" );
map.put( new Long(32) , new Long(43) );In the previous example, keys are validated by a simple InstanceofPredicate, which ensures that each
key is a String. The values are
validated with an OrPredicate, which
combines two EqualPredicates; values
are accepted if they are equal to the strings "green" or "red."
A PredicatedMap can work with
any Predicate no matter how simple or
complex. Passing in a null value for
either the key or value Predicate
instructs the PredicatedMap not to
validate keys or values. In the following example, a PredicatedMap decorates a HashMap to ensure that a Map contains valid Team values:
import org.apache.commons.collections.functors.AndPredicate;
import org.apache.commons.collections.map.PredicatedMap;
// Create the Predicates
ValidTeamPredicate validTeam = new ValidTeamPredicate( );
ValidCoachPredicate validCoach = new ValidCoachPredicate( );
// Tie two Predicates together into an AndPredicate
AndPredicate valuePredicate = new AndPredicate( validTeam, validCoach );
// Decorate a HashMap with a predicate on the value
Map teamMap = PredicatedMap.decorate( new HashMap( ), null, valuePredicate);
// Manufacture some teams
Team redSox = new Team( "Red Sox", new Coach( "Patrick", "Moloney") );
Team yankees= new Team( "Yankees", new Coach( "David", "McGarry") );
Team dodgers = new Team( "Dodgers", new Coach( "Nick", "Taylor") );
Team twins = new Team( null, new Coach( "Patrick", "Moloney") );
Team braves = new Team( "Braves", null );
// The following put calls should work fine
teamMap.put( "RedSox", redSox );
teamMap.put( "Yankees", yankees );
teamMap.put( "Dodgers", dodgers );
// This put should fail because the team name is null
try {
teamMap.put( "Twins", twins);
} catch( IllegalArgumentException iae ) {
System.out.println( "Twins put failed, as expected" );
}
// This put should fail because the coach is null
try {
teamMap.put( "Braves", braves);
} catch( IllegalArgumentException iae ) {
System.out.println( "Braves put failed, as expected" );
}An application can assume that every team in teamMap has met the following
requirements:
Every Team object must have
a non-null name property.
Every Team object must have
a non-null coach property, and this Coach object must have a first and last
name.
The previous example uses two Predicate objects to validate both the team
and the coach. These two custom predicates (ValidTeamPredicate and ValidCoachPredicate) are defined in Examples
Example 5-15 and Example 5-16. These Predicate objects are passed to the PredicatedMap.decorate( ) method to decorate a
Map with these conditions. The first
Predicate, ValidTeamPredicate, validates a Team object to see if it has a non-null name
property.
Example 5-16. Predicate to validate a Team's coach property
import org.apache.commons.collections.Predicate;
public class ValidCoachPredicate implements Predicate {
public boolean evaluate(Object object) {
boolean validCoach = false;
Team team = (Team) object;
if( team.getCoach( ) != null &&
team.getCoach( ).getFirstName( ) != null &&
team.getCoach( ).getLastName( ) != null ) {
validCoach = true;
}
return validCoach;
}
}The second Predicate, ValidCoachPredicate, validates a Team object, checking to see if the coach property is non-null, and that the coach has a first and last
name.
In Example 5-16, a
Predicate is created by combining the
ValidTeamPredicate and ValidCoachPredicate in an AndPredicate. A HashMap is then decorated with PredicatedMap.decorate( ), passing the
AndPredicate in as the predicate to
validate Map values. A few Team objects are created, all of which are
valid with the exception of the Twins and the Braves, and, as expected,
the
Twins and Braves cause put( ) to
throw an IllegalArgumentException.
