Decorate an existing Map
with
PredicatedMap
from Commons Collections. Predicate
s 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 Predicate
s 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
.