An elaborate builder class for Map<String, Object> (map-in-map)
pseudo-objects. A MapBuilder lets you write deeply nested values without having
to create the intermediate maps first. If they are missing, they will tacitly be
created. Map keys must not be null or an empty string. Map values can be
anything, including null.
Internally, a MapBuilder works with Path objects. See the
documentation for the Path class for how to specify path strings.
Example 1:
MapBuilder mb = new MapBuilder(); mb.set("person.address.street", "12 Revolutionary Rd.") .set("person.address.state", "CA") .set("person.firstName", "John") .set("person.lastName", "Smith") .set("person.dateOfBirth", LocalDate.of(1967, 4, 4)); Map<String, Object> map = mb.build();
Example 2:
Map<String, Object> map = new MapBuilder() .in("person") .set("firstName", "John") .set("lastName", "Smith") .set("dateOfBirth", LocalDate.of(1967, 4, 4)) .in("address") .set("street", "12 Revolutionary Rd.") .set("state", "CA") .up("person") .in("medical_status") .set("allergies", false) .set("smoker", true) .set("prescriptions", null) .build();
Although the MapBuilder class is primarily aimed at buildings maps, you can
also use it to read maps:
MapBuilder mb = new MapBuilder(someMap); String street = mb.get("person.address.street");
For more flexibility, use the PathWalker class.
- Author:
- Ayco Holleman
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic final classThrown when trying to write to a path that has already been set, or that extends beyond a path segment with a terminal value (anything other than a map). -
Method Summary
Modifier and TypeMethodDescriptionAppends the specified element to theCollectionfound at the specified path.static MapBuilderbegin()Creates a newMapBuilder.static MapBuilderCreates aMapBuilderthat starts out with the entries in the specified map.build()Returns theMapresulting from the write actions.<T> TReturns the value of the specified path if set, elsenull.Returns aMapBuilderfor the map at the specified path.booleanReturns whether the specified path is set to a terminal value (and hence cannot be extended).Jumps to another branch in the tree of nested maps.name()Returns the key used to embed the current map within the parent map.Returns aResultobject containing the value of the specified path, orResult.notAvailable()if the path is not set.root()Takes you back to the root map.Sets the specified path to the specified value.toString()Returns a string representation of the map created thus far.Unsets the value of the specified path.Returns aMapBuilderfor the parent map of the map currently being edited.where()Returns the full path to the current map.
-
Method Details
-
begin
Creates a newMapBuilder.- Returns:
- a new
MapBuilder
-
begin
Creates aMapBuilderthat starts out with the entries in the specified map. The map is read, but not modified.- Parameters:
map- The initialMap- Returns:
- a
MapBuilderthat starts out with the entries in the specified map
-
set
Sets the specified path to the specified value. It is not allowed to overwrite the value of a path that has already been set, even if set to
null. If necessary, useunset(String)to unset the path's value first.The value can be anything except a
MaporMapBuilder. Use thein()method to create a new map at the specified path. It is allowed to set a path's value tonull.- Parameters:
path- the path at which to write the valuevalue- the value- Returns:
- this
MapBuilder
-
add
Appends the specified element to the
Collectionfound at the specified path. If the path has not been set yet, it will first be set to an emptyArrayList, to which the element will then be added. If the path is already set to a non-Collectiontype, aMapBuilder.PathBlockedExceptionis thrown.- Parameters:
path- the pathelement- the element to add to the collection found or created at the specified path- Returns:
- this
MapBuilder
-
poll
Returns aResultobject containing the value of the specified path, orResult.notAvailable()if the path is not set.- Parameters:
path- the path- Returns:
- a
Resultobject containing the value of the specified path, orResult.notAvailable()if the path is not set - See Also:
-
get
Returns the value of the specified path if set, elsenull.- Type Parameters:
T- The type to cast the path's value to- Parameters:
path- the path- Returns:
- the value of the specified path if set, else
null
-
in
Returns aMapBuilderfor the map at the specified path. Once this method has been called, all subsequently specified paths (including for subsequent calls toin()) are taken relative to the specified path. If there is no map yet at the specified path, it will be created. Ancestral maps will be created as well, as and when needed. If any of the segments in the path (including the last segment) has already been set, aMapBuilder.PathBlockedExceptionis thrown.- Parameters:
path- the path to be used as the base path. The path will itself be interpreted as relative to the current base path- Returns:
- a
MapBuilderfor the map found or created at the specified path
-
jump
Jumps to another branch in the tree of nested maps. The difference betweenjumpandinis that the path passed tojumpis always taken as an absolute path (i.e. relative to the root map), while the path passed toinis taken relative to the path(s) passed to previous calls toinandjump.- Parameters:
path- the absolute path to be used as the base path- Returns:
- a
MapBuilderfor the map found or created at the specified path - See Also:
-
up
Returns a
MapBuilderfor the parent map of the map currently being edited. All subsequently specified paths will be taken relative to the parent map's path. AnIllegalStateExceptionis thrown when trying to exit out of the root map. This method must be passed the name of the parent map (the last segment of the parent map's path). AnIllegalArgumentExceptionis thrown if the argument does not equal the parent map's name. This is to make sure you will not accidentally start writing to the wrong map, and it makes the map-building code more intelligible.Map<String, Object> map = new MapBuilder() .in("person") .set("firstName", "John") .set("lastName", "Smith") .in("address") .set("street", "12 Revolutionary Rd.") .set("state", "CA") .up("person") .set("dateOfBirth", LocalDate.of(1967, 4, 4)) .build();You can chain
exitcalls. To exit from a map directly under the root map, specifynullor""(an empty string):MapBuilder mb = new MapBuilder(); .in("department.manager.address") .set("street", "Sunset Blvd") .up("manager") .up("department") .up(null) .set("foo", "bar");- Parameters:
parent- the name of the parent map- Returns:
- a
MapBuilderfor the parent map of the map currently being written to
-
root
Takes you back to the root map. All paths you specify will be interpreted as absolute paths again.- Returns:
- a
MapBuilderfor the root map
-
name
Returns the key used to embed the current map within the parent map. If the current map is the root map, an empty string is returned.- Returns:
- the key used to embed the current map within the parent map
-
where
Returns the full path to the current map. That is, the path relative to which allpatharguments (e.g. for theset()method) are taken.- Returns:
- the full path to the current map
-
isSet
Returns whether the specified path is set to a terminal value (and hence cannot be extended).- Parameters:
path- the path- Returns:
- whether it is set to a terminal value
-
unset
Unsets the value of the specified path. This method returns quietly for non-existent paths.- Parameters:
path- the path to unset.- Returns:
- this
MapBuilder
-
build
Returns theMapresulting from the write actions. The returned map is modifiable and retains the order in which the paths (now keys) were written. You can continue to use theMapBuilderafter a call to this method.- Returns:
- the
Mapresulting from the write actions
-
toString
Returns a string representation of the map created thus far.
-