Extending the global context
Zone handlers
The global context APIs treat the first path element of an access key as the name of a ZoneHandler (
/<zone>/<path>[#<value_path>]
). GC APIs then delegate store/retrieve operations to the corresponding zone handler.
Zone handlers are Java implementations of zero.core.context.zones.ZoneHandler . Zone handlers are registered via configuration, such as:
/config/zoneHandlers += {
"user" : "zero.core.context.zones.UserZoneHandler"
}
Type handlers
Type handlers are responsible for value manipulation, including appends. Type handlers are Java implementations of zero.core.context.zones.TypeHandler
To maintain support for nested value paths, implementations must consume their corresponding parameter from the value path and advance the valuePathOffset in parsedUri. See the source for zero.core.context.types.MapTypeHandler or zero.core.context.types.ListTypeHandler for specific examples.
Type handlers are registered by appending type/handler implementation key/value pairs to the map in the global context at /config/typeHandlers. For example, the handler implementation (zero.core.context.types.CommandTypeHandler) for the Command type (zero.core.context.types.commands.Command) is specified in configuration as:
/config/typeHandlers += {
"zero.core.context.types.commands.Command" : "zero.core.context.types.CommandTypeHandler"
}
Command handlers
The global context can be used to store behavior by associating commands with global context keys.
The Command type handler delegates all operations to the implementation of Command stored in the accessed GlobalContext location. This allows you to provide your own implementation of Command and implement the actions to be taken on GET, PUT, POST, and DELETE. For convenience, IBM® WebSphere® sMash provides a zero.core.context.types.commands.BaseCommandImpl with implementations of GET, PUT, POST, and DELETE which return Context.NO_ZONE_UPDATE. Returning Context.NO_ZONE_UPDATE causes no operation to take place.
Because the Command type already has a registered type handler, you do not need to add new type handlers when providing your own Command implementations.
Commands can be used to implement your own behavior. For example, you could defer evaluation of an expensive value until a get is actually called as follows:
@Test
public void testGetCommand() {
zput("/config/command", new BaseCommandImpl() {
@Override
public <V> V get(ParsedURI parsedUri) {
return (V) "foo";
}
});
assertEquals("foo", zget("/config/command"));
}
Another usage of Command would be to implement post to carry out your own custom action.
When using the default implementation of Command provided by BaseCommandImpl Command objects can not be replaced or deleted from the global context. If you need this behavior, you can override the corresponding methods in Command to allow it. For example, the following implementation allows the Command object to be deleted:
@Test
public void testDeleteableCommand() {
GlobalContext.zput("/test/deleteablecmd", new BaseCommandImpl() {
Object value = null;
public <T> T get(ParsedURI parsedUri) {
if (value == null) {
value = "original value";
}
return (T)value;
}
@Override
public <T> T delete(ParsedURI parsedUri) {
return (T) Context.NO_VALUE;
}
});
assertEquals(true, GlobalContext.zcontains("/test/deleteablecmd"));
GlobalContext.zdelete("/test/deleteablecmd");
assertEquals(false, GlobalContext.zcontains("/test/deleteablecmd"));
}