using afIoc::Injectusing afBeanUtils::TypeCoercerusing afBeanUtils::NotFoundErr** (Service) - Provides the config values. constmixin IocConfigSource {** Return the config value with the given id, optionally coercing it to the given type.** ** Throws 'ArgErr' if the ID could not be found. @Operatorabstract Obj? get(Str id, Type? coerceTo := null)** Returns a case-insensitive map of all the config valuesabstract Str:Obj? config()}internalconstclass IocConfigSourceImpl : IocConfigSource {privateconst TypeCoercer typeCoercer := CachingTypeCoercer()overrideconst Str:Obj? config @Inject privateconst FactoryDefaults factoryDefaults @Inject privateconst ApplicationDefaults applicationDefaultsnew make(|This|in){ in(this) config := factoryDefaults.config.rw config.setAll(applicationDefaults.config)this.config = config.toImmutable}override Obj? get(Str id, Type? coerceTo := null){if(!config.containsKey(id))throw ConfigNotFoundErr(ErrMsgs.configNotFound(id), config.keys) value := config[id]if(value == null)returnnullif(coerceTo == null || value.typeof.fits(coerceTo))return valuereturn typeCoercer.coerce(value, coerceTo)}}** Thrown when a config ID has not been mapped.@NoDocconstclass ConfigNotFoundErr : ArgErr, NotFoundErr {overrideconst Str?[] availableValuesnew make(Str msg, Obj?[] availableValues, Err? cause := null) : super(msg, cause){this.availableValues = availableValues.map {it?.toStr }.sort}override Str toStr(){ NotFoundErr.super.toStr }}