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
checkedisfalse, 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
checkedisfalse,nullis 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
checkedisfalse,nullis returned.- make
Creates a
TypeLookupwith the given map. All types are coerced to non-nullable types. AnArgErris 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.)