]> granicus.if.org Git - icinga2/commitdiff
Avoid accessing attributes for validators where not necessary 5967/head
authorGunnar Beutner <gunnar.beutner@icinga.com>
Thu, 11 Jan 2018 06:08:09 +0000 (07:08 +0100)
committerGunnar Beutner <gunnar.beutner@icinga.com>
Thu, 11 Jan 2018 07:20:16 +0000 (08:20 +0100)
44 files changed:
lib/base/application.cpp
lib/base/application.hpp
lib/base/configobject.cpp
lib/base/logger.cpp
lib/base/logger.hpp
lib/base/object.cpp
lib/base/object.hpp
lib/base/sysloglogger.cpp
lib/base/sysloglogger.hpp
lib/compat/compatlogger.cpp
lib/compat/compatlogger.hpp
lib/db_ido/dbconnection.cpp
lib/db_ido/dbconnection.hpp
lib/icinga/checkable.cpp
lib/icinga/checkable.hpp
lib/icinga/customvarobject.cpp
lib/icinga/customvarobject.hpp
lib/icinga/dependency.cpp
lib/icinga/dependency.hpp
lib/icinga/downtime.cpp
lib/icinga/downtime.hpp
lib/icinga/icingaapplication.cpp
lib/icinga/icingaapplication.hpp
lib/icinga/notification.cpp
lib/icinga/notification.hpp
lib/icinga/scheduleddowntime.cpp
lib/icinga/scheduleddowntime.hpp
lib/icinga/timeperiod.cpp
lib/icinga/timeperiod.hpp
lib/icinga/user.cpp
lib/icinga/user.hpp
lib/livestatus/livestatuslistener.cpp
lib/livestatus/livestatuslistener.hpp
lib/perfdata/graphitewriter.cpp
lib/perfdata/graphitewriter.hpp
lib/perfdata/influxdbwriter.cpp
lib/perfdata/influxdbwriter.hpp
lib/perfdata/perfdatawriter.cpp
lib/perfdata/perfdatawriter.hpp
lib/remote/apilistener.cpp
lib/remote/apilistener.hpp
lib/remote/zone.cpp
lib/remote/zone.hpp
tools/mkclass/classcompiler.cpp

index d135592a18e0e0c1db531c47205aa5134ed4af4a..0c325c728040d84e2d66db539a35a300805a29a6 100644 (file)
@@ -1564,10 +1564,10 @@ void Application::SetLastReloadFailed(double ts)
        m_LastReloadFailed = ts;
 }
 
-void Application::ValidateName(const String& value, const ValidationUtils& utils)
+void Application::ValidateName(const Lazy<String>& lvalue, const ValidationUtils& utils)
 {
-       ObjectImpl<Application>::ValidateName(value, utils);
+       ObjectImpl<Application>::ValidateName(lvalue, utils);
 
-       if (value != "app")
+       if (lvalue() != "app")
                BOOST_THROW_EXCEPTION(ValidationError(this, { "name" }, "Application object must be named 'app'."));
 }
index 6811c8936a5ca1c481adba75bb7cd1ffd3b234de..429d06aba81cd5595bbf8961590b1765123531fb 100644 (file)
@@ -174,7 +174,7 @@ protected:
 
        virtual void OnShutdown();
 
-       void ValidateName(const String& value, const ValidationUtils& utils) final;
+       void ValidateName(const Lazy<String>& lvalue, const ValidationUtils& utils) final;
 
 private:
        static Application::Ptr m_Instance; /**< The application instance. */
index d725afe9202c754e678b65f6034cd9522954dc19..824ec2630302d8b694c536c7ea4433966e2bb156 100644 (file)
@@ -210,7 +210,7 @@ void ConfigObject::ModifyAttribute(const String& attr, const Value& value, bool
        }
 
        ModAttrValidationUtils utils;
-       ValidateField(fid, newValue, utils);
+       ValidateField(fid, Lazy<Value>{newValue}, utils);
 
        SetField(fid, newValue);
 
index 227ed36942ab557138ef485bf967c33d6addcf50..9425a7fd1a3f87625153c1487c92bf8b20d1a52f 100644 (file)
@@ -183,14 +183,14 @@ bool Logger::IsTimestampEnabled()
        return m_TimestampEnabled;
 }
 
-void Logger::ValidateSeverity(const String& value, const ValidationUtils& utils)
+void Logger::ValidateSeverity(const Lazy<String>& lvalue, const ValidationUtils& utils)
 {
-       ObjectImpl<Logger>::ValidateSeverity(value, utils);
+       ObjectImpl<Logger>::ValidateSeverity(lvalue, utils);
 
        try {
-               StringToSeverity(value);
+               StringToSeverity(lvalue());
        } catch (...) {
-               BOOST_THROW_EXCEPTION(ValidationError(this, { "severity" }, "Invalid severity specified: " + value));
+               BOOST_THROW_EXCEPTION(ValidationError(this, { "severity" }, "Invalid severity specified: " + lvalue()));
        }
 }
 
index 1ed79b19776198e0b1f3f9bdd183e81960aa899b..40f4b455dabad3eb950ddfe3485d5bb02daf5531 100644 (file)
@@ -90,7 +90,7 @@ public:
        static void SetConsoleLogSeverity(LogSeverity logSeverity);
        static LogSeverity GetConsoleLogSeverity();
 
-       void ValidateSeverity(const String& value, const ValidationUtils& utils) final;
+       void ValidateSeverity(const Lazy<String>& lvalue, const ValidationUtils& utils) final;
 
 protected:
        void Start(bool runtimeCreated) override;
index fe91de5ac744ad078c849ebb00c3f6ff4e9611ee..68dfa0431c650e6239a2cbf357ca8cd225cf55fd 100644 (file)
@@ -168,7 +168,7 @@ void Object::Validate(int types, const ValidationUtils& utils)
        /* Nothing to do here. */
 }
 
-void Object::ValidateField(int id, const Value& value, const ValidationUtils& utils)
+void Object::ValidateField(int id, const Lazy<Value>& lvalue, const ValidationUtils& utils)
 {
        /* Nothing to do here. */
 }
index d6d9bc79fefb1ca374951cdd083562524d498b10..2b5d0037901014e903d0b483418274690cf7042e 100644 (file)
@@ -98,6 +98,63 @@ struct TypeHelper<T, true>
        }
 };
 
+template<typename T>
+struct Lazy
+{
+       using Accessor = std::function<T ()>;
+
+       explicit Lazy(T value)
+               : m_Cached(true), m_Value(value)
+       { }
+
+       explicit Lazy(Accessor accessor)
+               : m_Accessor(accessor)
+       { }
+
+       template<typename U>
+       explicit Lazy(const Lazy<U>& other)
+       {
+               if (other.m_Cached) {
+                       m_Accessor = Accessor();
+                       m_Value = static_cast<T>(other.m_Value);
+                       m_Cached = true;
+               } else {
+                       auto accessor = other.m_Accessor;
+                       m_Accessor = [accessor]() { return static_cast<T>(accessor()); };
+                       m_Cached = false;
+               }
+       }
+
+       template<typename U>
+       operator Lazy<U>() const
+       {
+               if (m_Cached)
+                       return Lazy<U>(m_Value);
+               else {
+                       Accessor accessor = m_Accessor;
+                       return Lazy<U>([accessor]() { return static_cast<U>(accessor()); });
+               }
+       }
+
+       const T& operator()() const
+       {
+               if (!m_Cached) {
+                       m_Value = m_Accessor();
+                       m_Cached = true;
+               }
+
+               return m_Value;
+       }
+
+private:
+       Accessor m_Accessor;
+       mutable bool m_Cached{false};
+       mutable T m_Value;
+
+       template<typename U>
+       friend struct Lazy;
+};
+
 /**
  * Base class for all heap-allocated objects. At least one of its methods
  * has to be virtual for RTTI to work.
@@ -124,7 +181,7 @@ public:
        virtual void SetFieldByName(const String& field, const Value& value, const DebugInfo& debugInfo);
        virtual bool HasOwnField(const String& field) const;
        virtual bool GetOwnField(const String& field, Value *result) const;
-       virtual void ValidateField(int id, const Value& value, const ValidationUtils& utils);
+       virtual void ValidateField(int id, const Lazy<Value>& lvalue, const ValidationUtils& utils);
        virtual void NotifyField(int id, const Value& cookie = Empty);
        virtual Object::Ptr NavigateField(int id) const;
 
index af95fa3da90f025bee3023d4b30ca407c2b06f3f..fb719997cc2afd8c61e681a39c682a8222cf1349 100644 (file)
@@ -103,13 +103,13 @@ void SyslogLogger::OnConfigLoaded()
                m_Facility = Convert::ToLong(facilityString);
 }
 
-void SyslogLogger::ValidateFacility(const String& value, const ValidationUtils& utils)
+void SyslogLogger::ValidateFacility(const Lazy<String>& lvalue, const ValidationUtils& utils)
 {
-       ObjectImpl<SyslogLogger>::ValidateFacility(value, utils);
+       ObjectImpl<SyslogLogger>::ValidateFacility(lvalue, utils);
 
-       if (m_FacilityMap.find(value) == m_FacilityMap.end()) {
+       if (m_FacilityMap.find(lvalue()) == m_FacilityMap.end()) {
                try {
-                       Convert::ToLong(value);
+                       Convert::ToLong(lvalue());
                } catch (const std::exception&) {
                        BOOST_THROW_EXCEPTION(ValidationError(this, { "facility" }, "Invalid facility specified."));
                }
index f61848b410ab0c88a57b13f02dde7282cb6b555b..e81ffe700fb963b20c5810fc396f9005f3f586e1 100644 (file)
@@ -42,7 +42,7 @@ public:
        static void StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata);
 
        void OnConfigLoaded() override;
-       void ValidateFacility(const String& value, const ValidationUtils& utils) override;
+       void ValidateFacility(const Lazy<String>& lvalue, const ValidationUtils& utils) override;
 
 protected:
        static std::map<String, int> m_FacilityMap;
index d618b6caab6257dfb7ada9db65f1bbfb3d715a67..498b434f3f977abdf95f22e08b74e7a975852eb7 100644 (file)
@@ -598,12 +598,12 @@ void CompatLogger::RotationTimerHandler()
        ScheduleNextRotation();
 }
 
-void CompatLogger::ValidateRotationMethod(const String& value, const ValidationUtils& utils)
+void CompatLogger::ValidateRotationMethod(const Lazy<String>& lvalue, const ValidationUtils& utils)
 {
-       ObjectImpl<CompatLogger>::ValidateRotationMethod(value, utils);
+       ObjectImpl<CompatLogger>::ValidateRotationMethod(lvalue, utils);
 
-       if (value != "HOURLY" && value != "DAILY" &&
-               value != "WEEKLY" && value != "MONTHLY" && value != "NONE") {
-               BOOST_THROW_EXCEPTION(ValidationError(this, { "rotation_method" }, "Rotation method '" + value + "' is invalid."));
+       if (lvalue() != "HOURLY" && lvalue() != "DAILY" &&
+               lvalue() != "WEEKLY" && lvalue() != "MONTHLY" && lvalue() != "NONE") {
+               BOOST_THROW_EXCEPTION(ValidationError(this, { "rotation_method" }, "Rotation method '" + lvalue() + "' is invalid."));
        }
 }
index 1cfb2a28e4a6167980c3345541038e99cfbf38a7..f12ae2e4ad32d6c44f1de612e95f84acf87d403d 100644 (file)
@@ -41,7 +41,7 @@ public:
 
        static void StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata);
 
-       void ValidateRotationMethod(const String& value, const ValidationUtils& utils) override;
+       void ValidateRotationMethod(const Lazy<String>& lvalue, const ValidationUtils& utils) override;
 
 protected:
        void Start(bool runtimeCreated) override;
index 9249697de258b119663ca53d79651a1b315ea16c..7202a24472e61662036799eee1e81c2a08a3c94c 100644 (file)
@@ -440,19 +440,19 @@ void DbConnection::PrepareDatabase()
        }
 }
 
-void DbConnection::ValidateFailoverTimeout(double value, const ValidationUtils& utils)
+void DbConnection::ValidateFailoverTimeout(const Lazy<double>& lvalue, const ValidationUtils& utils)
 {
-       ObjectImpl<DbConnection>::ValidateFailoverTimeout(value, utils);
+       ObjectImpl<DbConnection>::ValidateFailoverTimeout(lvalue, utils);
 
-       if (value < 60)
+       if (lvalue() < 60)
                BOOST_THROW_EXCEPTION(ValidationError(this, { "failover_timeout" }, "Failover timeout minimum is 60s."));
 }
 
-void DbConnection::ValidateCategories(const Array::Ptr& value, const ValidationUtils& utils)
+void DbConnection::ValidateCategories(const Lazy<Array::Ptr>& lvalue, const ValidationUtils& utils)
 {
-       ObjectImpl<DbConnection>::ValidateCategories(value, utils);
+       ObjectImpl<DbConnection>::ValidateCategories(lvalue, utils);
 
-       int filter = FilterArrayToInt(value, DbQuery::GetCategoryFilterMap(), 0);
+       int filter = FilterArrayToInt(lvalue(), DbQuery::GetCategoryFilterMap(), 0);
 
        if (filter != DbCatEverything && (filter & ~(DbCatInvalid | DbCatEverything | DbCatConfig | DbCatState |
                DbCatAcknowledgement | DbCatComment | DbCatDowntime | DbCatEventHandler | DbCatExternalCommand |
index 932e3e1b4bc6645a574b2c6c0e53800741930532..e1eb506334727e728c473e53807a91ed3ecd314e 100644 (file)
@@ -74,8 +74,8 @@ public:
        int GetQueryCount(RingBuffer::SizeType span);
        virtual int GetPendingQueryCount() const = 0;
 
-       void ValidateFailoverTimeout(double value, const ValidationUtils& utils) final;
-       void ValidateCategories(const Array::Ptr& value, const ValidationUtils& utils) final;
+       void ValidateFailoverTimeout(const Lazy<double>& lvalue, const ValidationUtils& utils) final;
+       void ValidateCategories(const Lazy<Array::Ptr>& lvalue, const ValidationUtils& utils) final;
 
 protected:
        void OnConfigLoaded() override;
index 13852e94e8c07e818d6a205775dab221d83d30ab..9b66eb2408818f58f6e5fa786738922d66fb96a5 100644 (file)
@@ -187,18 +187,18 @@ void Checkable::NotifyDowntimeEnd(const Downtime::Ptr& downtime)
                OnNotificationsRequested(checkable, NotificationDowntimeEnd, checkable->GetLastCheckResult(), downtime->GetAuthor(), downtime->GetComment(), nullptr);
 }
 
-void Checkable::ValidateCheckInterval(double value, const ValidationUtils& utils)
+void Checkable::ValidateCheckInterval(const Lazy<double>& lvalue, const ValidationUtils& utils)
 {
-       ObjectImpl<Checkable>::ValidateCheckInterval(value, utils);
+       ObjectImpl<Checkable>::ValidateCheckInterval(lvalue, utils);
 
-       if (value <= 0)
+       if (lvalue() <= 0)
                BOOST_THROW_EXCEPTION(ValidationError(this, { "check_interval" }, "Interval must be greater than 0."));
 }
 
-void Checkable::ValidateMaxCheckAttempts(int value, const ValidationUtils& utils)
+void Checkable::ValidateMaxCheckAttempts(const Lazy<int>& lvalue, const ValidationUtils& utils)
 {
-       ObjectImpl<Checkable>::ValidateMaxCheckAttempts(value, utils);
+       ObjectImpl<Checkable>::ValidateMaxCheckAttempts(lvalue, utils);
 
-       if (value <= 0)
+       if (lvalue() <= 0)
                BOOST_THROW_EXCEPTION(ValidationError(this, { "max_check_attempts" }, "Value must be greater than 0."));
 }
index b2061be299cc74cebc7bb282f129384f7d07d1df..107def55fc331e4e31beb6ab1d4d4f9e1ff2aab0 100644 (file)
@@ -191,8 +191,8 @@ public:
        void RemoveReverseDependency(const intrusive_ptr<Dependency>& dep);
        std::vector<intrusive_ptr<Dependency> > GetReverseDependencies() const;
 
-       void ValidateCheckInterval(double value, const ValidationUtils& utils) final;
-       void ValidateMaxCheckAttempts(int value, const ValidationUtils& utils) final;
+       void ValidateCheckInterval(const Lazy<double>& lvalue, const ValidationUtils& value) final;
+       void ValidateMaxCheckAttempts(const Lazy<int>& lvalue, const ValidationUtils& value) final;
 
        static void IncreasePendingChecks();
        static void DecreasePendingChecks();
index 0487def7329ac1b6a33b94f65cf4cdba842178fd..16d31df666f7a6011de872d8b80794e4825ac45a 100644 (file)
@@ -29,9 +29,9 @@ using namespace icinga;
 
 REGISTER_TYPE(CustomVarObject);
 
-void CustomVarObject::ValidateVars(const Dictionary::Ptr& value, const ValidationUtils& utils)
+void CustomVarObject::ValidateVars(const Lazy<Dictionary::Ptr>& lvalue, const ValidationUtils& utils)
 {
-       MacroProcessor::ValidateCustomVars(this, value);
+       MacroProcessor::ValidateCustomVars(this, lvalue());
 }
 
 int icinga::FilterArrayToInt(const Array::Ptr& typeFilters, const std::map<String, int>& filterMap, int defaultValue)
index 4cf16f66a33622de42a5e80e4b8707cedc539890..dbb14531ec25819f365c8ad4c223cd5d59711e11 100644 (file)
@@ -38,7 +38,7 @@ class CustomVarObject : public ObjectImpl<CustomVarObject>
 public:
        DECLARE_OBJECT(CustomVarObject);
 
-       void ValidateVars(const Dictionary::Ptr& value, const ValidationUtils& utils) final;
+       void ValidateVars(const Lazy<Dictionary::Ptr>& lvalue, const ValidationUtils& utils) final;
 };
 
 int FilterArrayToInt(const Array::Ptr& typeFilters, const std::map<String, int>& filterMap, int defaultValue);
index 42c5f4e6455095d3c50acee76951baa116dc2d87..6e02cfd4080f2817f5056c5191717df3534081a3 100644 (file)
@@ -209,11 +209,11 @@ TimePeriod::Ptr Dependency::GetPeriod() const
        return TimePeriod::GetByName(GetPeriodRaw());
 }
 
-void Dependency::ValidateStates(const Array::Ptr& value, const ValidationUtils& utils)
+void Dependency::ValidateStates(const Lazy<Array::Ptr>& lvalue, const ValidationUtils& utils)
 {
-       ObjectImpl<Dependency>::ValidateStates(value, utils);
+       ObjectImpl<Dependency>::ValidateStates(lvalue, utils);
 
-       int sfilter = FilterArrayToInt(value, Notification::GetStateFilterMap(), 0);
+       int sfilter = FilterArrayToInt(lvalue(), Notification::GetStateFilterMap(), 0);
 
        if (GetParentServiceName().IsEmpty() && (sfilter & ~(StateFilterUp | StateFilterDown)) != 0)
                BOOST_THROW_EXCEPTION(ValidationError(this, { "states" }, "State filter is invalid for host dependency."));
index 3f5775f345f497f5b7b8a5e0b8949e239bd201ef..820e0efb434e87d0b4113cfe8d842a803a8813ec 100644 (file)
@@ -49,7 +49,7 @@ public:
 
        bool IsAvailable(DependencyType dt) const;
 
-       void ValidateStates(const Array::Ptr& value, const ValidationUtils& utils) override;
+       void ValidateStates(const Lazy<Array::Ptr>& lvalue, const ValidationUtils& utils) override;
 
        static void EvaluateApplyRules(const intrusive_ptr<Host>& host);
        static void EvaluateApplyRules(const intrusive_ptr<Service>& service);
index 226c5af91fbf4e3b6e391c404e57acbfd8c33b9c..7428332d088ff4c994a1a710be72eb12ce345369 100644 (file)
@@ -409,18 +409,18 @@ void Downtime::DowntimesExpireTimerHandler()
        }
 }
 
-void Downtime::ValidateStartTime(const Timestamp& value, const ValidationUtils& utils)
+void Downtime::ValidateStartTime(const Lazy<Timestamp>& lvalue, const ValidationUtils& utils)
 {
-       ObjectImpl<Downtime>::ValidateStartTime(value, utils);
+       ObjectImpl<Downtime>::ValidateStartTime(lvalue, utils);
 
-       if (value <= 0)
+       if (lvalue() <= 0)
                BOOST_THROW_EXCEPTION(ValidationError(this, { "start_time" }, "Start time must be greater than 0."));
 }
 
-void Downtime::ValidateEndTime(const Timestamp& value, const ValidationUtils& utils)
+void Downtime::ValidateEndTime(const Lazy<Timestamp>& lvalue, const ValidationUtils& utils)
 {
-       ObjectImpl<Downtime>::ValidateEndTime(value, utils);
+       ObjectImpl<Downtime>::ValidateEndTime(lvalue, utils);
 
-       if (value <= 0)
+       if (lvalue() <= 0)
                BOOST_THROW_EXCEPTION(ValidationError(this, { "end_time" }, "End time must be greater than 0."));
 }
index 1c120c0199ce7bfe68ab7483298c527b7464644b..5149762b113e88de26822b966f51fd83f413c391 100644 (file)
@@ -70,8 +70,8 @@ protected:
        void Start(bool runtimeCreated) override;
        void Stop(bool runtimeRemoved) override;
 
-       void ValidateStartTime(const Timestamp& value, const ValidationUtils& utils) override;
-       void ValidateEndTime(const Timestamp& value, const ValidationUtils& utils) override;
+       void ValidateStartTime(const Lazy<Timestamp>& lvalue, const ValidationUtils& utils) override;
+       void ValidateEndTime(const Lazy<Timestamp>& lvalue, const ValidationUtils& utils) override;
 
 private:
        ObjectImpl<Checkable>::Ptr m_Checkable;
index 3008bfb968e97ede0a5565b93edb036974f630c5..3a32586a4128282b635836faa50f36e24d27f234 100644 (file)
@@ -289,7 +289,7 @@ String IcingaApplication::GetNodeName() const
        return ScriptGlobal::Get("NodeName");
 }
 
-void IcingaApplication::ValidateVars(const Dictionary::Ptr& value, const ValidationUtils& utils)
+void IcingaApplication::ValidateVars(const Lazy<Dictionary::Ptr>& lvalue, const ValidationUtils& utils)
 {
-       MacroProcessor::ValidateCustomVars(this, value);
+       MacroProcessor::ValidateCustomVars(this, lvalue());
 }
index 9329a202a4410c0082a6989ae261acf3b281fa39..b5b1b951bdd32971c628c74d82d4031f9342eca8 100644 (file)
@@ -52,7 +52,7 @@ public:
 
        String GetNodeName() const;
 
-       void ValidateVars(const Dictionary::Ptr& value, const ValidationUtils& utils) override;
+       void ValidateVars(const Lazy<Dictionary::Ptr>& lvalue, const ValidationUtils& utils) override;
 
 private:
        void DumpProgramState();
index f85c90a43ac0f715d5e6152e49aebb7e5a086abe..8771f424096bdb8d679c0b0c983328dcefc83ac3 100644 (file)
@@ -642,11 +642,11 @@ void Notification::Validate(int types, const ValidationUtils& utils)
                BOOST_THROW_EXCEPTION(ValidationError(this, std::vector<String>(), "Validation failed: No users/user_groups specified."));
 }
 
-void Notification::ValidateStates(const Array::Ptr& value, const ValidationUtils& utils)
+void Notification::ValidateStates(const Lazy<Array::Ptr>& lvalue, const ValidationUtils& utils)
 {
-       ObjectImpl<Notification>::ValidateStates(value, utils);
+       ObjectImpl<Notification>::ValidateStates(lvalue, utils);
 
-       int filter = FilterArrayToInt(value, GetStateFilterMap(), 0);
+       int filter = FilterArrayToInt(lvalue(), GetStateFilterMap(), 0);
 
        if (GetServiceName().IsEmpty() && (filter == -1 || (filter & ~(StateFilterUp | StateFilterDown)) != 0))
                BOOST_THROW_EXCEPTION(ValidationError(this, { "states" }, "State filter is invalid."));
@@ -655,11 +655,11 @@ void Notification::ValidateStates(const Array::Ptr& value, const ValidationUtils
                BOOST_THROW_EXCEPTION(ValidationError(this, { "states" }, "State filter is invalid."));
 }
 
-void Notification::ValidateTypes(const Array::Ptr& value, const ValidationUtils& utils)
+void Notification::ValidateTypes(const Lazy<Array::Ptr>& lvalue, const ValidationUtils& utils)
 {
-       ObjectImpl<Notification>::ValidateTypes(value, utils);
+       ObjectImpl<Notification>::ValidateTypes(lvalue, utils);
 
-       int filter = FilterArrayToInt(value, GetTypeFilterMap(), 0);
+       int filter = FilterArrayToInt(lvalue(), GetTypeFilterMap(), 0);
 
        if (filter == -1 || (filter & ~(NotificationDowntimeStart | NotificationDowntimeEnd | NotificationDowntimeRemoved |
                NotificationCustom | NotificationAcknowledgement | NotificationProblem | NotificationRecovery |
index b87bb702ce0e319f11ed0fb5f491c83b9454cfc3..27b78f531acaccdb89a6785bdf62c3edcd246e48 100644 (file)
@@ -106,8 +106,8 @@ public:
 
        void Validate(int types, const ValidationUtils& utils) override;
 
-       void ValidateStates(const Array::Ptr& value, const ValidationUtils& utils) override;
-       void ValidateTypes(const Array::Ptr& value, const ValidationUtils& utils) override;
+       void ValidateStates(const Lazy<Array::Ptr>& lvalue, const ValidationUtils& utils) override;
+       void ValidateTypes(const Lazy<Array::Ptr>& lvalue, const ValidationUtils& utils) override;
 
        static void EvaluateApplyRules(const intrusive_ptr<Host>& host);
        static void EvaluateApplyRules(const intrusive_ptr<Service>& service);
index b1948096434a0902323833717bedbb33dfdbc716..6c702946e5c38f2889dba327bc15ce2f5840b25c 100644 (file)
@@ -196,11 +196,11 @@ void ScheduledDowntime::CreateNextDowntime()
                GetFixed(), String(), GetDuration(), GetName(), GetName());
 }
 
-void ScheduledDowntime::ValidateRanges(const Dictionary::Ptr& value, const ValidationUtils& utils)
+void ScheduledDowntime::ValidateRanges(const Lazy<Dictionary::Ptr>& lvalue, const ValidationUtils& utils)
 {
-       ObjectImpl<ScheduledDowntime>::ValidateRanges(value, utils);
+       ObjectImpl<ScheduledDowntime>::ValidateRanges(lvalue, utils);
 
-       if (!value)
+       if (!lvalue())
                return;
 
        /* create a fake time environment to validate the definitions */
@@ -208,8 +208,8 @@ void ScheduledDowntime::ValidateRanges(const Dictionary::Ptr& value, const Valid
        tm reference = Utility::LocalTime(refts);
        Array::Ptr segments = new Array();
 
-       ObjectLock olock(value);
-       for (const Dictionary::Pair& kv : value) {
+       ObjectLock olock(lvalue());
+       for (const Dictionary::Pair& kv : lvalue()) {
                try {
                        tm begin_tm, end_tm;
                        int stride;
index 2b27eaaa8f3b2aff9980fda46488673954ee9c0a..9e5751e417cf7f09a6de690ca8af6189c3f71af5 100644 (file)
@@ -48,7 +48,7 @@ public:
        static void EvaluateApplyRules(const intrusive_ptr<Host>& host);
        static void EvaluateApplyRules(const intrusive_ptr<Service>& service);
 
-       void ValidateRanges(const Dictionary::Ptr& value, const ValidationUtils& utils) override;
+       void ValidateRanges(const Lazy<Dictionary::Ptr>& lvalue, const ValidationUtils& utils) override;
 
 protected:
        void OnAllConfigLoaded() override;
index 626d03f985289e1f8b32fac7aee18785bf3e6c3f..13ee6bcfbabad07e958a36a41bb42c44ce23412d 100644 (file)
@@ -381,9 +381,9 @@ void TimePeriod::Dump()
        Log(LogDebug, "TimePeriod", "---");
 }
 
-void TimePeriod::ValidateRanges(const Dictionary::Ptr& value, const ValidationUtils& utils)
+void TimePeriod::ValidateRanges(const Lazy<Dictionary::Ptr>& lvalue, const ValidationUtils& utils)
 {
-       if (!value)
+       if (!lvalue())
                return;
 
        /* create a fake time environment to validate the definitions */
@@ -391,8 +391,8 @@ void TimePeriod::ValidateRanges(const Dictionary::Ptr& value, const ValidationUt
        tm reference = Utility::LocalTime(refts);
        Array::Ptr segments = new Array();
 
-       ObjectLock olock(value);
-       for (const Dictionary::Pair& kv : value) {
+       ObjectLock olock(lvalue());
+       for (const Dictionary::Pair& kv : lvalue()) {
                try {
                        tm begin_tm, end_tm;
                        int stride;
index 9fc01850ad998de46fd6afd60d16fd379099a13e..fe1c7d651ab66272b04de86c5f8929d3461f7e6d 100644 (file)
@@ -46,7 +46,7 @@ public:
        bool IsInside(double ts) const;
        double FindNextTransition(double begin);
 
-       void ValidateRanges(const Dictionary::Ptr& value, const ValidationUtils& utils) override;
+       void ValidateRanges(const Lazy<Dictionary::Ptr>& lvalue, const ValidationUtils& utils) override;
 
 private:
        void AddSegment(double s, double end);
index b7e92b03decd49d3e1c9d6a06fc7e16d30466311..7059c8438e5c481dcd4403dd89dd27d27e1367a1 100644 (file)
@@ -97,21 +97,21 @@ TimePeriod::Ptr User::GetPeriod() const
        return TimePeriod::GetByName(GetPeriodRaw());
 }
 
-void User::ValidateStates(const Array::Ptr& value, const ValidationUtils& utils)
+void User::ValidateStates(const Lazy<Array::Ptr>& lvalue, const ValidationUtils& utils)
 {
-       ObjectImpl<User>::ValidateStates(value, utils);
+       ObjectImpl<User>::ValidateStates(lvalue, utils);
 
-       int filter = FilterArrayToInt(value, Notification::GetStateFilterMap(), 0);
+       int filter = FilterArrayToInt(lvalue(), Notification::GetStateFilterMap(), 0);
 
        if (filter == -1 || (filter & ~(StateFilterUp | StateFilterDown | StateFilterOK | StateFilterWarning | StateFilterCritical | StateFilterUnknown)) != 0)
                BOOST_THROW_EXCEPTION(ValidationError(this, { "states" }, "State filter is invalid."));
 }
 
-void User::ValidateTypes(const Array::Ptr& value, const ValidationUtils& utils)
+void User::ValidateTypes(const Lazy<Array::Ptr>& lvalue, const ValidationUtils& utils)
 {
-       ObjectImpl<User>::ValidateTypes(value, utils);
+       ObjectImpl<User>::ValidateTypes(lvalue, utils);
 
-       int filter = FilterArrayToInt(value, Notification::GetTypeFilterMap(), 0);
+       int filter = FilterArrayToInt(lvalue(), Notification::GetTypeFilterMap(), 0);
 
        if (filter == -1 || (filter & ~(NotificationDowntimeStart | NotificationDowntimeEnd | NotificationDowntimeRemoved |
                NotificationCustom | NotificationAcknowledgement | NotificationProblem | NotificationRecovery |
index 527777cec8b825c7c3575cce3451e0d38a1eb6d3..28e0b8bcb4599cd159fec619c5cb52440816202b 100644 (file)
@@ -44,8 +44,8 @@ public:
        /* Notifications */
        TimePeriod::Ptr GetPeriod() const;
 
-       void ValidateStates(const Array::Ptr& value, const ValidationUtils& utils) override;
-       void ValidateTypes(const Array::Ptr& value, const ValidationUtils& utils) override;
+       void ValidateStates(const Lazy<Array::Ptr>& lvalue, const ValidationUtils& utils) override;
+       void ValidateTypes(const Lazy<Array::Ptr>& lvalue, const ValidationUtils& utils) override;
 
 protected:
        void Stop(bool runtimeRemoved) override;
index 6a5b864187262992bf4230a85d949646a774f1b8..164b44fc1bc553f31e1d00a1bd0890c68a2f15d5 100644 (file)
@@ -220,10 +220,10 @@ void LivestatusListener::ClientHandler(const Socket::Ptr& client)
 }
 
 
-void LivestatusListener::ValidateSocketType(const String& value, const ValidationUtils& utils)
+void LivestatusListener::ValidateSocketType(const Lazy<String>& lvalue, const ValidationUtils& utils)
 {
-       ObjectImpl<LivestatusListener>::ValidateSocketType(value, utils);
+       ObjectImpl<LivestatusListener>::ValidateSocketType(lvalue, utils);
 
-       if (value != "unix" && value != "tcp")
-               BOOST_THROW_EXCEPTION(ValidationError(this, { "socket_type" }, "Socket type '" + value + "' is invalid."));
+       if (lvalue() != "unix" && lvalue() != "tcp")
+               BOOST_THROW_EXCEPTION(ValidationError(this, { "socket_type" }, "Socket type '" + lvalue() + "' is invalid."));
 }
index b917bb3e46986aa9104cf818e38dd7c1cbe93982..3292a3eb80fd9886c1f77e68d9cf659bb7069123 100644 (file)
@@ -45,7 +45,7 @@ public:
        static int GetClientsConnected();
        static int GetConnections();
 
-       void ValidateSocketType(const String& value, const ValidationUtils& utils) override;
+       void ValidateSocketType(const Lazy<String>& lvalue, const ValidationUtils& utils) override;
 
 protected:
        void Start(bool runtimeCreated) override;
index c1e832128eee328d760a33a1a95a664c8529bbd4..b21c139d69d610f42e6b4c0ff931e11b45e68a96 100644 (file)
@@ -342,18 +342,18 @@ Value GraphiteWriter::EscapeMacroMetric(const Value& value)
                return EscapeMetric(value);
 }
 
-void GraphiteWriter::ValidateHostNameTemplate(const String& value, const ValidationUtils& utils)
+void GraphiteWriter::ValidateHostNameTemplate(const Lazy<String>& lvalue, const ValidationUtils& utils)
 {
-       ObjectImpl<GraphiteWriter>::ValidateHostNameTemplate(value, utils);
+       ObjectImpl<GraphiteWriter>::ValidateHostNameTemplate(lvalue, utils);
 
-       if (!MacroProcessor::ValidateMacroString(value))
-               BOOST_THROW_EXCEPTION(ValidationError(this, { "host_name_template" }, "Closing $ not found in macro format string '" + value + "'."));
+       if (!MacroProcessor::ValidateMacroString(lvalue()))
+               BOOST_THROW_EXCEPTION(ValidationError(this, { "host_name_template" }, "Closing $ not found in macro format string '" + lvalue() + "'."));
 }
 
-void GraphiteWriter::ValidateServiceNameTemplate(const String& value, const ValidationUtils& utils)
+void GraphiteWriter::ValidateServiceNameTemplate(const Lazy<String>& lvalue, const ValidationUtils& utils)
 {
-       ObjectImpl<GraphiteWriter>::ValidateServiceNameTemplate(value, utils);
+       ObjectImpl<GraphiteWriter>::ValidateServiceNameTemplate(lvalue, utils);
 
-       if (!MacroProcessor::ValidateMacroString(value))
-               BOOST_THROW_EXCEPTION(ValidationError(this, { "service_name_template" }, "Closing $ not found in macro format string '" + value + "'."));
+       if (!MacroProcessor::ValidateMacroString(lvalue()))
+               BOOST_THROW_EXCEPTION(ValidationError(this, { "service_name_template" }, "Closing $ not found in macro format string '" + lvalue() + "'."));
 }
index e5652add07334873bc2a258b15853fc3cd11eca8..05bc8bb43d0430bc8932b179b902428e2458eea8 100644 (file)
@@ -44,8 +44,8 @@ public:
 
        static void StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata);
 
-       void ValidateHostNameTemplate(const String& value, const ValidationUtils& utils) override;
-       void ValidateServiceNameTemplate(const String& value, const ValidationUtils& utils) override;
+       void ValidateHostNameTemplate(const Lazy<String>& lvalue, const ValidationUtils& utils) override;
+       void ValidateServiceNameTemplate(const Lazy<String>& lvalue, const ValidationUtils& utils) override;
 
 protected:
        void OnConfigLoaded() override;
index ef1a4dd52f424a77bad9b3752b491abada247a65..a614064500fd2669e7c9ff7a3c17a28eb484d6f4 100644 (file)
@@ -494,15 +494,15 @@ void InfluxdbWriter::Flush()
        }
 }
 
-void InfluxdbWriter::ValidateHostTemplate(const Dictionary::Ptr& value, const ValidationUtils& utils)
+void InfluxdbWriter::ValidateHostTemplate(const Lazy<Dictionary::Ptr>& lvalue, const ValidationUtils& utils)
 {
-       ObjectImpl<InfluxdbWriter>::ValidateHostTemplate(value, utils);
+       ObjectImpl<InfluxdbWriter>::ValidateHostTemplate(lvalue, utils);
 
-       String measurement = value->Get("measurement");
+       String measurement = lvalue()->Get("measurement");
        if (!MacroProcessor::ValidateMacroString(measurement))
                BOOST_THROW_EXCEPTION(ValidationError(this, { "host_template", "measurement" }, "Closing $ not found in macro format string '" + measurement + "'."));
 
-       Dictionary::Ptr tags = value->Get("tags");
+       Dictionary::Ptr tags = lvalue()->Get("tags");
        if (tags) {
                ObjectLock olock(tags);
                for (const Dictionary::Pair& pair : tags) {
@@ -512,15 +512,15 @@ void InfluxdbWriter::ValidateHostTemplate(const Dictionary::Ptr& value, const Va
        }
 }
 
-void InfluxdbWriter::ValidateServiceTemplate(const Dictionary::Ptr& value, const ValidationUtils& utils)
+void InfluxdbWriter::ValidateServiceTemplate(const Lazy<Dictionary::Ptr>& lvalue, const ValidationUtils& utils)
 {
-       ObjectImpl<InfluxdbWriter>::ValidateServiceTemplate(value, utils);
+       ObjectImpl<InfluxdbWriter>::ValidateServiceTemplate(lvalue, utils);
 
-       String measurement = value->Get("measurement");
+       String measurement = lvalue()->Get("measurement");
        if (!MacroProcessor::ValidateMacroString(measurement))
                BOOST_THROW_EXCEPTION(ValidationError(this, { "service_template", "measurement" }, "Closing $ not found in macro format string '" + measurement + "'."));
 
-       Dictionary::Ptr tags = value->Get("tags");
+       Dictionary::Ptr tags = lvalue()->Get("tags");
        if (tags) {
                ObjectLock olock(tags);
                for (const Dictionary::Pair& pair : tags) {
index 8332c2fb2927ef8a6f95bc589b04694bc8262239..323d1f91156ff13da4bacd49b52270858ca88dd0 100644 (file)
@@ -44,8 +44,8 @@ public:
 
        static void StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata);
 
-       void ValidateHostTemplate(const Dictionary::Ptr& value, const ValidationUtils& utils) override;
-       void ValidateServiceTemplate(const Dictionary::Ptr& value, const ValidationUtils& utils) override;
+       void ValidateHostTemplate(const Lazy<Dictionary::Ptr>& lvalue, const ValidationUtils& utils) override;
+       void ValidateServiceTemplate(const Lazy<Dictionary::Ptr>& lvalue, const ValidationUtils& utils) override;
 
 protected:
        void OnConfigLoaded() override;
index 5b726a9376bc100646074c923d497e7613e4e541..9d987c7d8625878961e94b08694e49c6f7bc0f00 100644 (file)
@@ -158,18 +158,18 @@ void PerfdataWriter::RotationTimerHandler()
        RotateFile(m_HostOutputFile, GetHostTempPath(), GetHostPerfdataPath());
 }
 
-void PerfdataWriter::ValidateHostFormatTemplate(const String& value, const ValidationUtils& utils)
+void PerfdataWriter::ValidateHostFormatTemplate(const Lazy<String>& lvalue, const ValidationUtils& utils)
 {
-       ObjectImpl<PerfdataWriter>::ValidateHostFormatTemplate(value, utils);
+       ObjectImpl<PerfdataWriter>::ValidateHostFormatTemplate(lvalue, utils);
 
-       if (!MacroProcessor::ValidateMacroString(value))
-               BOOST_THROW_EXCEPTION(ValidationError(this, { "host_format_template" }, "Closing $ not found in macro format string '" + value + "'."));
+       if (!MacroProcessor::ValidateMacroString(lvalue()))
+               BOOST_THROW_EXCEPTION(ValidationError(this, { "host_format_template" }, "Closing $ not found in macro format string '" + lvalue() + "'."));
 }
 
-void PerfdataWriter::ValidateServiceFormatTemplate(const String& value, const ValidationUtils& utils)
+void PerfdataWriter::ValidateServiceFormatTemplate(const Lazy<String>& lvalue, const ValidationUtils& utils)
 {
-       ObjectImpl<PerfdataWriter>::ValidateServiceFormatTemplate(value, utils);
+       ObjectImpl<PerfdataWriter>::ValidateServiceFormatTemplate(lvalue, utils);
 
-       if (!MacroProcessor::ValidateMacroString(value))
-               BOOST_THROW_EXCEPTION(ValidationError(this, { "service_format_template" }, "Closing $ not found in macro format string '" + value + "'."));
+       if (!MacroProcessor::ValidateMacroString(lvalue()))
+               BOOST_THROW_EXCEPTION(ValidationError(this, { "service_format_template" }, "Closing $ not found in macro format string '" + lvalue() + "'."));
 }
index 64bd36fb593fa66e028b6dc5c761a1428f36728e..098fb84548f4639317e2ea3b083744dad714e4f4 100644 (file)
@@ -42,8 +42,8 @@ public:
 
        static void StatsFunc(const Dictionary::Ptr& status, const Array::Ptr& perfdata);
 
-       void ValidateHostFormatTemplate(const String& value, const ValidationUtils& utils) override;
-       void ValidateServiceFormatTemplate(const String& value, const ValidationUtils& utils) override;
+       void ValidateHostFormatTemplate(const Lazy<String>& lvalue, const ValidationUtils& utils) override;
+       void ValidateServiceFormatTemplate(const Lazy<String>& lvalue, const ValidationUtils& utils) override;
 
 protected:
        void Start(bool runtimeCreated) override;
index e639ee8c0ec6c5cddcc9a51e990f4bebfc3b942b..65ad4d64c8ba483fc598acb7e0fcd45f428f2699 100644 (file)
@@ -1399,14 +1399,14 @@ Endpoint::Ptr ApiListener::GetLocalEndpoint() const
        return m_LocalEndpoint;
 }
 
-void ApiListener::ValidateTlsProtocolmin(const String& value, const ValidationUtils& utils)
+void ApiListener::ValidateTlsProtocolmin(const Lazy<String>& lvalue, const ValidationUtils& utils)
 {
-       ObjectImpl<ApiListener>::ValidateTlsProtocolmin(value, utils);
+       ObjectImpl<ApiListener>::ValidateTlsProtocolmin(lvalue, utils);
 
-       if (value != SSL_TXT_TLSV1
+       if (lvalue() != SSL_TXT_TLSV1
 #ifdef SSL_TXT_TLSV1_1
-               && value != SSL_TXT_TLSV1_1 &&
-               value != SSL_TXT_TLSV1_2
+               && lvalue() != SSL_TXT_TLSV1_1 &&
+               lvalue() != SSL_TXT_TLSV1_2
 #endif /* SSL_TXT_TLSV1_1 */
                ) {
                String message = "Invalid TLS version. Must be one of '" SSL_TXT_TLSV1 "'";
index 5405914a6e505fcaa6dac55fb7580b40e043704d..ecd1b38cb5da36561c7ac6ffbfbdbb3a0420d4c4 100644 (file)
@@ -114,7 +114,7 @@ protected:
        void Start(bool runtimeCreated) override;
        void Stop(bool runtimeDeleted) override;
 
-       void ValidateTlsProtocolmin(const String& value, const ValidationUtils& utils) override;
+       void ValidateTlsProtocolmin(const Lazy<String>& lvalue, const ValidationUtils& utils) override;
 
 private:
        std::shared_ptr<SSL_CTX> m_SSLContext;
index c171c78f45690ff562efac7cd308a5a4f688327f..acfff3c5a87a2f198fd8e95a81546120d29b2225 100644 (file)
@@ -144,11 +144,11 @@ Zone::Ptr Zone::GetLocalZone()
        return local->GetZone();
 }
 
-void Zone::ValidateEndpointsRaw(const Array::Ptr& value, const ValidationUtils& utils)
+void Zone::ValidateEndpointsRaw(const Lazy<Array::Ptr>& lvalue, const ValidationUtils& utils)
 {
-       ObjectImpl<Zone>::ValidateEndpointsRaw(value, utils);
+       ObjectImpl<Zone>::ValidateEndpointsRaw(lvalue, utils);
 
-       if (value && value->GetLength() > 2) {
+       if (lvalue() && lvalue()->GetLength() > 2) {
                Log(LogWarning, "Zone")
                        << "The Zone object '" << GetName() << "' has more than two endpoints."
                        << " Due to a known issue this type of configuration is strongly"
index dd5918641c07c334b78c9f2141ea4bf807e5dbd9..158847de64741c0e1823232b6d71282d3d7ca763 100644 (file)
@@ -50,7 +50,7 @@ public:
        static Zone::Ptr GetLocalZone();
 
 protected:
-       void ValidateEndpointsRaw(const Array::Ptr& value, const ValidationUtils& utils) override;
+       void ValidateEndpointsRaw(const Lazy<Array::Ptr>& lvalue, const ValidationUtils& utils) override;
 
 private:
        Zone::Ptr m_Parent;
index c8ade32eab45dffc751c67fe14844bd44992fda9..1899e6d296ecdd52f25063754f4489d9c6470159 100644 (file)
@@ -470,53 +470,56 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo&)
 
        for (const Field& field : klass.Fields) {
                m_Impl << "\t" << "if (" << (field.Attributes & (FAEphemeral|FAConfig|FAState)) << " & types)" << std::endl
-                               << "\t\t" << "Validate" << field.GetFriendlyName() << "(Get" << field.GetFriendlyName() << "(), utils);" << std::endl;
+                               << "\t\t" << "Validate" << field.GetFriendlyName() << "(Lazy<" << field.Type.GetRealType() << ">([this]() { return Get" << field.GetFriendlyName() << "(); }), utils);" << std::endl;
        }
 
        m_Impl << "}" << std::endl << std::endl;
 
        for (const Field& field : klass.Fields) {
-               std::string argName;
+               std::string argName, valName;
 
-               if (field.Type.ArrayRank > 0)
+               if (field.Type.ArrayRank > 0) {
                        argName = "avalue";
-               else
+                       valName = "value";
+               } else {
                        argName = "value";
+                       valName = "value()";
+               }
 
-               m_Header << "\t" << "void SimpleValidate" << field.GetFriendlyName() << "(" << field.Type.GetArgumentType() << " " << argName << ", const ValidationUtils& utils);" << std::endl;
+               m_Header << "\t" << "void SimpleValidate" << field.GetFriendlyName() << "(const Lazy<" << field.Type.GetRealType() << ">& " << argName << ", const ValidationUtils& utils);" << std::endl;
 
-               m_Impl << "void ObjectImpl<" << klass.Name << ">::SimpleValidate" << field.GetFriendlyName() << "(" << field.Type.GetArgumentType() << " " << argName << ", const ValidationUtils& utils)" << std::endl
+               m_Impl << "void ObjectImpl<" << klass.Name << ">::SimpleValidate" << field.GetFriendlyName() << "(const Lazy<" << field.Type.GetRealType() << ">& " << argName << ", const ValidationUtils& utils)" << std::endl
                        << "{" << std::endl;
 
                if (field.Attributes & FARequired) {
                        if (field.Type.GetRealType().find("::Ptr") != std::string::npos)
-                               m_Impl << "\t" << "if (!" << argName << ")" << std::endl;
+                               m_Impl << "\t" << "if (!" << argName << "())" << std::endl;
                        else
-                               m_Impl << "\t" << "if (" << argName << ".IsEmpty())" << std::endl;
+                               m_Impl << "\t" << "if (" << argName << "().IsEmpty())" << std::endl;
 
                        m_Impl << "\t\t" << "BOOST_THROW_EXCEPTION(ValidationError(dynamic_cast<ConfigObject *>(this), { \"" << field.Name << R"(" }, "Attribute must not be empty."));)" << std::endl << std::endl;
                }
 
                if (field.Attributes & FADeprecated) {
                        if (field.Type.GetRealType().find("::Ptr") != std::string::npos)
-                               m_Impl << "\t" << "if (" << argName << ")" << std::endl;
+                               m_Impl << "\t" << "if (" << argName << "())" << std::endl;
                        else
-                               m_Impl << "\t" << "if (" << argName << " != GetDefault" << field.GetFriendlyName() << "())" << std::endl;
+                               m_Impl << "\t" << "if (" << argName << "() != GetDefault" << field.GetFriendlyName() << "())" << std::endl;
 
                        m_Impl << "\t\t" << "Log(LogWarning, \"" << klass.Name << "\") << \"Attribute '" << field.Name << R"(' for object '" << dynamic_cast<ConfigObject *>(this)->GetName() << "' of type '" << dynamic_cast<ConfigObject *>(this)->GetReflectionType()->GetName() << "' is deprecated and should not be used.";)" << std::endl;
                }
 
                if (field.Type.ArrayRank > 0) {
-                       m_Impl << "\t" << "if (avalue) {" << std::endl
-                               << "\t\t" << "ObjectLock olock(avalue);" << std::endl
-                               << "\t\t" << "for (const Value& value : avalue) {" << std::endl;
+                       m_Impl << "\t" << "if (avalue()) {" << std::endl
+                               << "\t\t" << "ObjectLock olock(avalue());" << std::endl
+                               << "\t\t" << "for (const Value& value : avalue()) {" << std::endl;
                }
 
                std::string ftype = FieldTypeToIcingaName(field, true);
 
                if (ftype == "Value") {
-                       m_Impl << "\t" << "if (value.IsObjectType<Function>()) {" << std::endl
-                               << "\t\t" << "Function::Ptr func = value;" << std::endl
+                       m_Impl << "\t" << "if (" << valName << ".IsObjectType<Function>()) {" << std::endl
+                               << "\t\t" << "Function::Ptr func = " << valName << ";" << std::endl
                                << "\t\t" << "if (func->IsDeprecated())" << std::endl
                                << "\t\t\t" << "Log(LogWarning, \"" << klass.Name << "\") << \"Attribute '" << field.Name << R"(' for object '" << dynamic_cast<ConfigObject *>(this)->GetName() << "' of type '" << dynamic_cast<ConfigObject *>(this)->GetReflectionType()->GetName() << "' is set to a deprecated function: " << func->GetName();)" << std::endl
                                << "\t" << "}" << std::endl << std::endl;
@@ -526,18 +529,18 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo&)
                        m_Impl << "\t" << "if (";
 
                        if (field.Type.ArrayRank > 0)
-                               m_Impl << "value.IsEmpty() || ";
+                               m_Impl << valName << ".IsEmpty() || ";
                        else
-                               m_Impl << "!value.IsEmpty() && ";
+                               m_Impl << "!" << valName << ".IsEmpty() && ";
 
-                       m_Impl << "!utils.ValidateName(\"" << field.Type.TypeName << "\", value))" << std::endl
-                               << "\t\t" << "BOOST_THROW_EXCEPTION(ValidationError(dynamic_cast<ConfigObject *>(this), { \"" << field.Name << R"(" }, "Object '" + value + "' of type ')" << field.Type.TypeName
+                       m_Impl << "!utils.ValidateName(\"" << field.Type.TypeName << "\", " << valName << "))" << std::endl
+                               << "\t\t" << "BOOST_THROW_EXCEPTION(ValidationError(dynamic_cast<ConfigObject *>(this), { \"" << field.Name << R"(" }, "Object '" + )" << valName << R"( + "' of type ')" << field.Type.TypeName
                                << "' does not exist.\"));" << std::endl;
                } else if (field.Type.ArrayRank > 0 && (ftype == "Number" || ftype == "Boolean")) {
                        m_Impl << "\t" << "try {" << std::endl
-                               << "\t\t" << "Convert::ToDouble(value);" << std::endl
+                               << "\t\t" << "Convert::ToDouble(" << valName << ");" << std::endl
                                << "\t" << "} catch (const std::invalid_argument&) {" << std::endl
-                               << "\t\t" << "BOOST_THROW_EXCEPTION(ValidationError(dynamic_cast<ConfigObject *>(this), { \"" << field.Name << R"(", "Array element '" + value + "' of type '" + value.GetReflectionType()->GetName() + "' is not valid here; expected type ')" << ftype << "'.\"));" << std::endl
+                               << "\t\t" << "BOOST_THROW_EXCEPTION(ValidationError(dynamic_cast<ConfigObject *>(this), { \"" << field.Name << R"(", "Array element '" + " << valName << " + "' of type '" + " << valName << ".GetReflectionType()->GetName() + "' is not valid here; expected type ')" << ftype << "'.\"));" << std::endl
                                << "\t" << "}" << std::endl;
                }
 
@@ -649,14 +652,14 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo&)
                
                /* ValidateField */
                m_Header << "public:" << std::endl
-                               << "\t" << "void ValidateField(int id, const Value& value, const ValidationUtils& utils) override;" << std::endl;
+                               << "\t" << "void ValidateField(int id, const Lazy<Value>& lvalue, const ValidationUtils& utils) override;" << std::endl;
 
-               m_Impl << "void ObjectImpl<" << klass.Name << ">::ValidateField(int id, const Value& value, const ValidationUtils& utils)" << std::endl
+               m_Impl << "void ObjectImpl<" << klass.Name << ">::ValidateField(int id, const Lazy<Value>& lvalue, const ValidationUtils& utils)" << std::endl
                        << "{" << std::endl;
 
                if (!klass.Parent.empty())
                        m_Impl << "\t" << "int real_id = id - " << klass.Parent << "::TypeInstance->GetFieldCount(); " << std::endl
-                               << "\t" << "if (real_id < 0) { " << klass.Parent << "::ValidateField(id, value, utils); return; }" << std::endl;
+                               << "\t" << "if (real_id < 0) { " << klass.Parent << "::ValidateField(id, lvalue, utils); return; }" << std::endl;
 
                m_Impl << "\t" << "switch (";
 
@@ -673,9 +676,9 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo&)
                                << "\t\t\t" << "Validate" << field.GetFriendlyName() << "(";
                        
                        if (field.Attributes & FAEnum)
-                               m_Impl << "static_cast<" << field.Type.GetRealType() << ">(static_cast<int>(";
+                               m_Impl << "static_cast<Lazy<" << field.Type.GetRealType() << "> >(static_cast<Lazy<int> >(";
 
-                       m_Impl << "value";
+                       m_Impl << "lvalue";
                        
                        if (field.Attributes & FAEnum)
                                m_Impl << "))";
@@ -1039,7 +1042,7 @@ void ClassCompiler::HandleClass(const Klass& klass, const ClassDebugInfo&)
                /* validators */
                for (const Field& field : klass.Fields) {
                        m_Header << "protected:" << std::endl
-                                       << "\t" << "virtual void Validate" << field.GetFriendlyName() << "(" << field.Type.GetArgumentType() << " value, const ValidationUtils& utils);" << std::endl;
+                                       << "\t" << "virtual void Validate" << field.GetFriendlyName() << "(const Lazy<" << field.Type.GetRealType() << ">& lvalue, const ValidationUtils& utils);" << std::endl;
                }
 
                /* instance variables */
@@ -1144,7 +1147,7 @@ void ClassCompiler::CodeGenValidator(const std::string& name, const std::string&
                                << "\t\t\t" << "if (utils.ValidateName(\"" << rule.Type << "\", value))" << std::endl
                                << "\t\t\t\t" << "return;" << std::endl
                                << "\t\t\t" << "else" << std::endl
-                               << "\t\t\t\t" << R"(BOOST_THROW_EXCEPTION(ValidationError(dynamic_pointer_cast<ConfigObject>(object), location, "Object '" + value + "' of type ')" << rule.Type << "' does not exist.\"));" << std::endl
+                               << "\t\t\t\t" << R"(BOOST_THROW_EXCEPTION(ValidationError(dynamic_pointer_cast<ConfigObject>(object), location, "Object '" + ")" << "xxx" << R"( + "' of type ')" << rule.Type << "' does not exist.\"));" << std::endl
                                << "\t\t" << "}" << std::endl;
                }
 
@@ -1309,12 +1312,12 @@ void ClassCompiler::HandleValidator(const Validator& validator, const ClassDebug
                CodeGenValidator(it.first.first + it.first.second, it.first.first, validator.Rules, it.second.Name, it.second.Type, ValidatorField);
 
        for (const auto& it : m_MissingValidators) {
-               m_Impl << "void ObjectImpl<" << it.first.first << ">::Validate" << it.first.second << "(" << it.second.Type.GetArgumentType() << " value, const ValidationUtils& utils)" << std::endl
+               m_Impl << "void ObjectImpl<" << it.first.first << ">::Validate" << it.first.second << "(const Lazy<" << it.second.Type.GetRealType() << ">& lvalue, const ValidationUtils& utils)" << std::endl
                        << "{" << std::endl
-                       << "\t" << "SimpleValidate" << it.first.second << "(value, utils);" << std::endl
+                       << "\t" << "SimpleValidate" << it.first.second << "(lvalue, utils);" << std::endl
                        << "\t" << "std::vector<String> location;" << std::endl
                        << "\t" << "location.emplace_back(\"" << it.second.Name << "\");" << std::endl
-                       << "\t" << "TIValidate" << it.first.first << it.first.second << "(this, value, location, utils);" << std::endl
+                       << "\t" << "TIValidate" << it.first.first << it.first.second << "(this, lvalue(), location, utils);" << std::endl
                        << "\t" << "location.pop_back();" << std::endl
                        << "}" << std::endl << std::endl;
        }
@@ -1325,9 +1328,9 @@ void ClassCompiler::HandleValidator(const Validator& validator, const ClassDebug
 void ClassCompiler::HandleMissingValidators()
 {
        for (const auto& it : m_MissingValidators) {
-               m_Impl << "void ObjectImpl<" << it.first.first << ">::Validate" << it.first.second << "(" << it.second.Type.GetArgumentType() << " value, const ValidationUtils& utils)" << std::endl
+               m_Impl << "void ObjectImpl<" << it.first.first << ">::Validate" << it.first.second << "(const Lazy<" << it.second.Type.GetRealType() << ">& lvalue, const ValidationUtils& utils)" << std::endl
                        << "{" << std::endl
-                       << "\t" << "SimpleValidate" << it.first.second << "(value, utils);" << std::endl
+                       << "\t" << "SimpleValidate" << it.first.second << "(lvalue, utils);" << std::endl
                        << "}" << std::endl << std::endl;
        }