const classafBeanUtils::TypeLookup
sys::Obj afBeanUtils::TypeLookup
@
Js
Looks up values via a type inheritance search.
Example, if a TypeLookup
was created with Obj#, Num#
and Int#
, the inheritance and matching types would look like:
Type findParent() findChildren() Obj Obj Obj, Num, Int | Num Num Num, Int | Int Int Int
Note that findParent()
and findChildren()
return the value associated with the type, not the type itself. They also match the given type if TypeLookup
was created with it, hence findParent()
above matches itself.
While the above results are quite obvious, TypeLookup
is more useful when passed a type it doesn't know about:
findParent(Float#) // --> Num# findChildren(Float#) // --> Err
When searching the type hierarchy for a closest match (see findParent()
), note that TypeLookup
also searches mixins.
Example usages can be found in:
- IoC: All known implementations of a mixin are looked up via
findChildren()
- BedSheet: Strategies for handling Err types are looked up via
findParent()
If performance is required, then use Concurrent to create a TypeLookup
that caches the lookups. Full code for a CachingTypeLookup
is given below:
using afBeanUtils using afConcurrent** A 'TypeLookup' that caches the lookup results.internal const class CachingTypeLookup : TypeLookup { private const AtomicMap parentCache := AtomicMap() private const AtomicMap childrenCache := AtomicMap() new make(Type:Obj? values) : super(values) { }** Cache the lookup resultsoverride Obj? findParent(Type type, Bool checked := true) { nonNullable := type.toNonNullable return parentCache.getOrAdd(nonNullable) { doFindParent(nonNullable, checked) } }** Cache the lookup resultsoverride Obj?[] findChildren(Type type, Bool checked := true) { nonNullable := type.toNonNullable return childrenCache.getOrAdd(nonNullable) { doFindChildren(nonNullable, checked) } }** Clears the lookup cacheVoid clear() { parentCache.clear childrenCache.clear } }
- findChildren
virtual Obj?[] findChildren(Type type, Bool checked := true)
Returns the values of the children of the given type. Note an exact match is performed first. Example:
strategy := StrategyRegistry( [Obj#:1, Num#:2, Int#:3] ) strategy.findChildren(Obj#) // --> [1, 2, 3] strategy.findChildren(Num#) // --> [2, 3] strategy.findChildren(Float#) // --> Err
If no children are found and
checked
isfalse
, an empty list is returned.- findExact
Obj? findExact(Type exact, Bool checked := true)
Returns the value that matches the given type. This is just standard Map behaviour.
If no match is found and
checked
isfalse
,null
is returned.- findParent
virtual Obj? findParent(Type type, Bool checked := true)
Returns the value of the closest parent of the given type. Note an exact match is performed first. Example:
strategy := StrategyRegistry( [Obj#:1, Num#:2, Int#:3] ) strategy.findClosestParent(Obj#) // --> 1 strategy.findClosestParent(Num#) // --> 2 strategy.findClosestParent(Float#) // --> 2 strategy.findClosestParent(Wotever#) // --> Err
If no parent is found and
checked
isfalse
,null
is returned.- make
Creates a
TypeLookup
with the given map. All types are coerced to non-nullable types. AnArgErr
is thrown if a duplicate is found in the process.- types
Type[] types()
Returns a list of all the types this lookup is configured for. (Handy for debug / error messages.)