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 results
override Obj? findParent(Type type, Bool checked := true) {
nonNullable := type.toNonNullable
return parentCache.getOrAdd(nonNullable) { doFindParent(nonNullable, checked) }
}
** Cache the lookup results
override Obj?[] findChildren(Type type, Bool checked := true) {
nonNullable := type.toNonNullable
return parentCache.getOrAdd(nonNullable) { doFindChildren(nonNullable, checked) }
}
** Clears the lookup cache
Void clear() {
parentCache.clear
childrenCache.clear
}
}
- findChildren
virtual Obj?[] findChildren(Type type, Bool checked := true)Returns the values of the children of the given type. 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 (or the given type should ). 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.