#include "base/exception.hpp"
#include "base/objectlock.hpp"
#include "base/utility.hpp"
#include "base/convert.hpp"
#include "base/debug.hpp"
#include "base/dependencygraph.hpp"
#include "base/logger.hpp"
#include "base/function.hpp"
#include "base/configobject.hpp"
#include "base/configtype.hpp"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wunused-variable"
namespace icinga
{

TypeImpl<OpenTsdbWriter>::TypeImpl()
{ }

TypeImpl<OpenTsdbWriter>::~TypeImpl()
{ }

String TypeImpl<OpenTsdbWriter>::GetName() const
{
	return "OpenTsdbWriter";
}

int TypeImpl<OpenTsdbWriter>::GetAttributes() const
{
	return 0;
}

Type::Ptr TypeImpl<OpenTsdbWriter>::GetBaseType() const
{
	return ConfigObject::TypeInstance;
}

int TypeImpl<OpenTsdbWriter>::GetFieldId(const String& name) const
{
	int offset = ConfigObject::TypeInstance->GetFieldCount();

	switch (static_cast<int>(Utility::SDBM(name, 1))) {
		case 99:
			if (name == "connected")
				return offset + 7;

			break;
		case 100:
			if (name == "disconnect_timeout")
				return offset + 2;

			break;
		case 101:
			if (name == "enable_ha")
				return offset + 5;
			if (name == "enable_generic_metrics")
				return offset + 6;

			break;
		case 104:
			if (name == "host")
				return offset + 0;
			if (name == "host_template")
				return offset + 3;

			break;
		case 112:
			if (name == "port")
				return offset + 1;

			break;
		case 115:
			if (name == "service_template")
				return offset + 4;
			if (name == "should_connect")
				return offset + 8;

			break;
	}

	return ConfigObject::TypeInstance->GetFieldId(name);
}

Field TypeImpl<OpenTsdbWriter>::GetFieldInfo(int id) const
{
	int real_id = id - ConfigObject::TypeInstance->GetFieldCount();
	if (real_id < 0) { return ConfigObject::TypeInstance->GetFieldInfo(id); }
	switch (real_id) {
		case 0:
			return {0, "String", "host", "host", nullptr, 2, 0};
		case 1:
			return {1, "String", "port", "port", nullptr, 2, 0};
		case 2:
			return {2, "Number", "disconnect_timeout", "disconnect_timeout", nullptr, 2, 0};
		case 3:
			return {3, "Dictionary", "host_template", "host_template", nullptr, 2, 0};
		case 4:
			return {4, "Dictionary", "service_template", "service_template", nullptr, 2, 0};
		case 5:
			return {5, "Boolean", "enable_ha", "enable_ha", nullptr, 2, 0};
		case 6:
			return {6, "Boolean", "enable_generic_metrics", "enable_generic_metrics", nullptr, 2, 0};
		case 7:
			return {7, "Boolean", "connected", "connected", nullptr, 1025, 0};
		case 8:
			return {8, "Boolean", "should_connect", "should_connect", nullptr, 1025, 0};
		default:
			throw std::runtime_error("Invalid field ID.");
	}
}

int TypeImpl<OpenTsdbWriter>::GetFieldCount() const
{
	return 9 + ConfigObject::TypeInstance->GetFieldCount();
}

ObjectFactory TypeImpl<OpenTsdbWriter>::GetFactory() const
{
	return TypeHelper<OpenTsdbWriter, false>::GetFactory();
}

int TypeImpl<OpenTsdbWriter>::GetActivationPriority() const
{
	return 100;
}

void TypeImpl<OpenTsdbWriter>::RegisterAttributeHandler(int fieldId, const Type::AttributeHandler& callback)
{
	int real_id = fieldId - ConfigObject::TypeInstance->GetFieldCount(); 
	if (real_id < 0) { ConfigObject::TypeInstance->RegisterAttributeHandler(fieldId, callback); return; }
	switch (real_id) {
		case 0:
			ObjectImpl<OpenTsdbWriter>::OnHostChanged.connect(callback);
			break;
		case 1:
			ObjectImpl<OpenTsdbWriter>::OnPortChanged.connect(callback);
			break;
		case 2:
			ObjectImpl<OpenTsdbWriter>::OnDisconnectTimeoutChanged.connect(callback);
			break;
		case 3:
			ObjectImpl<OpenTsdbWriter>::OnHostTemplateChanged.connect(callback);
			break;
		case 4:
			ObjectImpl<OpenTsdbWriter>::OnServiceTemplateChanged.connect(callback);
			break;
		case 5:
			ObjectImpl<OpenTsdbWriter>::OnEnableHaChanged.connect(callback);
			break;
		case 6:
			ObjectImpl<OpenTsdbWriter>::OnEnableGenericMetricsChanged.connect(callback);
			break;
		case 7:
			ObjectImpl<OpenTsdbWriter>::OnConnectedChanged.connect(callback);
			break;
		case 8:
			ObjectImpl<OpenTsdbWriter>::OnShouldConnectChanged.connect(callback);
			break;
		default:
			throw std::runtime_error("Invalid field ID.");
	}
}

void ObjectImpl<OpenTsdbWriter>::Validate(int types, const ValidationUtils& utils)
{
	ConfigObject::Validate(types, utils);

	if (2 & types)
		ValidateHost(Lazy<String>([this]() { return GetHost(); }), utils);
	if (2 & types)
		ValidatePort(Lazy<String>([this]() { return GetPort(); }), utils);
	if (2 & types)
		ValidateDisconnectTimeout(Lazy<double>([this]() { return GetDisconnectTimeout(); }), utils);
	if (2 & types)
		ValidateHostTemplate(Lazy<Dictionary::Ptr>([this]() { return GetHostTemplate(); }), utils);
	if (2 & types)
		ValidateServiceTemplate(Lazy<Dictionary::Ptr>([this]() { return GetServiceTemplate(); }), utils);
	if (2 & types)
		ValidateEnableHa(Lazy<bool>([this]() { return GetEnableHa(); }), utils);
	if (2 & types)
		ValidateEnableGenericMetrics(Lazy<bool>([this]() { return GetEnableGenericMetrics(); }), utils);
	if (1 & types)
		ValidateConnected(Lazy<bool>([this]() { return GetConnected(); }), utils);
	if (1 & types)
		ValidateShouldConnect(Lazy<bool>([this]() { return GetShouldConnect(); }), utils);
}

void ObjectImpl<OpenTsdbWriter>::SimpleValidateHost(const Lazy<String>& value, const ValidationUtils& utils)
{
}

void ObjectImpl<OpenTsdbWriter>::SimpleValidatePort(const Lazy<String>& value, const ValidationUtils& utils)
{
}

void ObjectImpl<OpenTsdbWriter>::SimpleValidateDisconnectTimeout(const Lazy<double>& value, const ValidationUtils& utils)
{
}

void ObjectImpl<OpenTsdbWriter>::SimpleValidateHostTemplate(const Lazy<Dictionary::Ptr>& value, const ValidationUtils& utils)
{
}

void ObjectImpl<OpenTsdbWriter>::SimpleValidateServiceTemplate(const Lazy<Dictionary::Ptr>& value, const ValidationUtils& utils)
{
}

void ObjectImpl<OpenTsdbWriter>::SimpleValidateEnableHa(const Lazy<bool>& value, const ValidationUtils& utils)
{
}

void ObjectImpl<OpenTsdbWriter>::SimpleValidateEnableGenericMetrics(const Lazy<bool>& value, const ValidationUtils& utils)
{
}

void ObjectImpl<OpenTsdbWriter>::SimpleValidateConnected(const Lazy<bool>& value, const ValidationUtils& utils)
{
}

void ObjectImpl<OpenTsdbWriter>::SimpleValidateShouldConnect(const Lazy<bool>& value, const ValidationUtils& utils)
{
}

ObjectImpl<OpenTsdbWriter>::ObjectImpl()
{
	SetHost(GetDefaultHost(), true);
	SetPort(GetDefaultPort(), true);
	SetDisconnectTimeout(GetDefaultDisconnectTimeout(), true);
	SetHostTemplate(GetDefaultHostTemplate(), true);
	SetServiceTemplate(GetDefaultServiceTemplate(), true);
	SetEnableHa(GetDefaultEnableHa(), true);
	SetEnableGenericMetrics(GetDefaultEnableGenericMetrics(), true);
	SetConnected(GetDefaultConnected(), true);
	SetShouldConnect(GetDefaultShouldConnect(), true);
}

ObjectImpl<OpenTsdbWriter>::~ObjectImpl()
{ }

void ObjectImpl<OpenTsdbWriter>::SetField(int id, const Value& value, bool suppress_events, const Value& cookie)
{
	int real_id = id - ConfigObject::TypeInstance->GetFieldCount(); 
	if (real_id < 0) { ConfigObject::SetField(id, value, suppress_events, cookie); return; }
	switch (real_id) {
		case 0:
			SetHost(value, suppress_events, cookie);
			break;
		case 1:
			SetPort(value, suppress_events, cookie);
			break;
		case 2:
			SetDisconnectTimeout(value, suppress_events, cookie);
			break;
		case 3:
			SetHostTemplate(value, suppress_events, cookie);
			break;
		case 4:
			SetServiceTemplate(value, suppress_events, cookie);
			break;
		case 5:
			SetEnableHa(value, suppress_events, cookie);
			break;
		case 6:
			SetEnableGenericMetrics(value, suppress_events, cookie);
			break;
		case 7:
			SetConnected(value, suppress_events, cookie);
			break;
		case 8:
			SetShouldConnect(value, suppress_events, cookie);
			break;
		default:
			throw std::runtime_error("Invalid field ID.");
	}
}

Value ObjectImpl<OpenTsdbWriter>::GetField(int id) const
{
	int real_id = id - ConfigObject::TypeInstance->GetFieldCount(); 
	if (real_id < 0) { return ConfigObject::GetField(id); }
	switch (real_id) {
		case 0:
			return GetHost();
		case 1:
			return GetPort();
		case 2:
			return GetDisconnectTimeout();
		case 3:
			return GetHostTemplate();
		case 4:
			return GetServiceTemplate();
		case 5:
			return GetEnableHa();
		case 6:
			return GetEnableGenericMetrics();
		case 7:
			return GetConnected();
		case 8:
			return GetShouldConnect();
		default:
			throw std::runtime_error("Invalid field ID.");
	}
}

void ObjectImpl<OpenTsdbWriter>::ValidateField(int id, const Lazy<Value>& lvalue, const ValidationUtils& utils)
{
	int real_id = id - ConfigObject::TypeInstance->GetFieldCount(); 
	if (real_id < 0) { ConfigObject::ValidateField(id, lvalue, utils); return; }
	switch (real_id) {
		case 0:
			ValidateHost(lvalue, utils);
			break;
		case 1:
			ValidatePort(lvalue, utils);
			break;
		case 2:
			ValidateDisconnectTimeout(lvalue, utils);
			break;
		case 3:
			ValidateHostTemplate(lvalue, utils);
			break;
		case 4:
			ValidateServiceTemplate(lvalue, utils);
			break;
		case 5:
			ValidateEnableHa(lvalue, utils);
			break;
		case 6:
			ValidateEnableGenericMetrics(lvalue, utils);
			break;
		case 7:
			ValidateConnected(lvalue, utils);
			break;
		case 8:
			ValidateShouldConnect(lvalue, utils);
			break;
		default:
			throw std::runtime_error("Invalid field ID.");
	}
}

void ObjectImpl<OpenTsdbWriter>::NotifyField(int id, const Value& cookie)
{
	int real_id = id - ConfigObject::TypeInstance->GetFieldCount(); 
	if (real_id < 0) { ConfigObject::NotifyField(id, cookie); return; }
	switch (real_id) {
		case 0:
			NotifyHost(cookie);
			break;
		case 1:
			NotifyPort(cookie);
			break;
		case 2:
			NotifyDisconnectTimeout(cookie);
			break;
		case 3:
			NotifyHostTemplate(cookie);
			break;
		case 4:
			NotifyServiceTemplate(cookie);
			break;
		case 5:
			NotifyEnableHa(cookie);
			break;
		case 6:
			NotifyEnableGenericMetrics(cookie);
			break;
		case 7:
			NotifyConnected(cookie);
			break;
		case 8:
			NotifyShouldConnect(cookie);
			break;
		default:
			throw std::runtime_error("Invalid field ID.");
	}
}

Object::Ptr ObjectImpl<OpenTsdbWriter>::NavigateField(int id) const
{
	int real_id = id - ConfigObject::TypeInstance->GetFieldCount(); 
	if (real_id < 0) { return ConfigObject::NavigateField(id); }
	throw std::runtime_error("Invalid field ID.");
}

String ObjectImpl<OpenTsdbWriter>::GetHost() const
{
	return m_Host.load();
}

String ObjectImpl<OpenTsdbWriter>::GetPort() const
{
	return m_Port.load();
}

double ObjectImpl<OpenTsdbWriter>::GetDisconnectTimeout() const
{
	return m_DisconnectTimeout.load();
}

Dictionary::Ptr ObjectImpl<OpenTsdbWriter>::GetHostTemplate() const
{
	return m_HostTemplate.load();
}

Dictionary::Ptr ObjectImpl<OpenTsdbWriter>::GetServiceTemplate() const
{
	return m_ServiceTemplate.load();
}

bool ObjectImpl<OpenTsdbWriter>::GetEnableHa() const
{
	return m_EnableHa.load();
}

bool ObjectImpl<OpenTsdbWriter>::GetEnableGenericMetrics() const
{
	return m_EnableGenericMetrics.load();
}

bool ObjectImpl<OpenTsdbWriter>::GetConnected() const
{
	return m_Connected.load();
}

bool ObjectImpl<OpenTsdbWriter>::GetShouldConnect() const
{
	return m_ShouldConnect.load();
}

void ObjectImpl<OpenTsdbWriter>::SetHost(const String& value, bool suppress_events, const Value& cookie)
{
	m_Host.store(value);
	if (!suppress_events) {
		NotifyHost(cookie);
	}

}

void ObjectImpl<OpenTsdbWriter>::SetPort(const String& value, bool suppress_events, const Value& cookie)
{
	m_Port.store(value);
	if (!suppress_events) {
		NotifyPort(cookie);
	}

}

void ObjectImpl<OpenTsdbWriter>::SetDisconnectTimeout(double value, bool suppress_events, const Value& cookie)
{
	m_DisconnectTimeout.store(value);
	if (!suppress_events) {
		NotifyDisconnectTimeout(cookie);
	}

}

void ObjectImpl<OpenTsdbWriter>::SetHostTemplate(const Dictionary::Ptr& value, bool suppress_events, const Value& cookie)
{
	m_HostTemplate.store(value);
	if (!suppress_events) {
		NotifyHostTemplate(cookie);
	}

}

void ObjectImpl<OpenTsdbWriter>::SetServiceTemplate(const Dictionary::Ptr& value, bool suppress_events, const Value& cookie)
{
	m_ServiceTemplate.store(value);
	if (!suppress_events) {
		NotifyServiceTemplate(cookie);
	}

}

void ObjectImpl<OpenTsdbWriter>::SetEnableHa(bool value, bool suppress_events, const Value& cookie)
{
	m_EnableHa.store(value);
	if (!suppress_events) {
		NotifyEnableHa(cookie);
	}

}

void ObjectImpl<OpenTsdbWriter>::SetEnableGenericMetrics(bool value, bool suppress_events, const Value& cookie)
{
	m_EnableGenericMetrics.store(value);
	if (!suppress_events) {
		NotifyEnableGenericMetrics(cookie);
	}

}

void ObjectImpl<OpenTsdbWriter>::SetConnected(bool value, bool suppress_events, const Value& cookie)
{
	m_Connected.store(value);
	if (!suppress_events) {
		NotifyConnected(cookie);
	}

}

void ObjectImpl<OpenTsdbWriter>::SetShouldConnect(bool value, bool suppress_events, const Value& cookie)
{
	m_ShouldConnect.store(value);
	if (!suppress_events) {
		NotifyShouldConnect(cookie);
	}

}

void ObjectImpl<OpenTsdbWriter>::NotifyHost(const Value& cookie)
{
	auto *dobj = dynamic_cast<ConfigObject *>(this);
	if (!dobj || dobj->IsActive())
		OnHostChanged(static_cast<OpenTsdbWriter *>(this), cookie);
}

void ObjectImpl<OpenTsdbWriter>::NotifyPort(const Value& cookie)
{
	auto *dobj = dynamic_cast<ConfigObject *>(this);
	if (!dobj || dobj->IsActive())
		OnPortChanged(static_cast<OpenTsdbWriter *>(this), cookie);
}

void ObjectImpl<OpenTsdbWriter>::NotifyDisconnectTimeout(const Value& cookie)
{
	auto *dobj = dynamic_cast<ConfigObject *>(this);
	if (!dobj || dobj->IsActive())
		OnDisconnectTimeoutChanged(static_cast<OpenTsdbWriter *>(this), cookie);
}

void ObjectImpl<OpenTsdbWriter>::NotifyHostTemplate(const Value& cookie)
{
	auto *dobj = dynamic_cast<ConfigObject *>(this);
	if (!dobj || dobj->IsActive())
		OnHostTemplateChanged(static_cast<OpenTsdbWriter *>(this), cookie);
}

void ObjectImpl<OpenTsdbWriter>::NotifyServiceTemplate(const Value& cookie)
{
	auto *dobj = dynamic_cast<ConfigObject *>(this);
	if (!dobj || dobj->IsActive())
		OnServiceTemplateChanged(static_cast<OpenTsdbWriter *>(this), cookie);
}

void ObjectImpl<OpenTsdbWriter>::NotifyEnableHa(const Value& cookie)
{
	auto *dobj = dynamic_cast<ConfigObject *>(this);
	if (!dobj || dobj->IsActive())
		OnEnableHaChanged(static_cast<OpenTsdbWriter *>(this), cookie);
}

void ObjectImpl<OpenTsdbWriter>::NotifyEnableGenericMetrics(const Value& cookie)
{
	auto *dobj = dynamic_cast<ConfigObject *>(this);
	if (!dobj || dobj->IsActive())
		OnEnableGenericMetricsChanged(static_cast<OpenTsdbWriter *>(this), cookie);
}

void ObjectImpl<OpenTsdbWriter>::NotifyConnected(const Value& cookie)
{
	auto *dobj = dynamic_cast<ConfigObject *>(this);
	if (!dobj || dobj->IsActive())
		OnConnectedChanged(static_cast<OpenTsdbWriter *>(this), cookie);
}

void ObjectImpl<OpenTsdbWriter>::NotifyShouldConnect(const Value& cookie)
{
	auto *dobj = dynamic_cast<ConfigObject *>(this);
	if (!dobj || dobj->IsActive())
		OnShouldConnectChanged(static_cast<OpenTsdbWriter *>(this), cookie);
}

String ObjectImpl<OpenTsdbWriter>::GetDefaultHost() const
{
	 return "127.0.0.1"; 
}

String ObjectImpl<OpenTsdbWriter>::GetDefaultPort() const
{
	 return "4242"; 
}

double ObjectImpl<OpenTsdbWriter>::GetDefaultDisconnectTimeout() const
{
	 return 10; 
}

Dictionary::Ptr ObjectImpl<OpenTsdbWriter>::GetDefaultHostTemplate() const
{
	 return new Dictionary(); 
}

Dictionary::Ptr ObjectImpl<OpenTsdbWriter>::GetDefaultServiceTemplate() const
{
	 return new Dictionary(); 
}

bool ObjectImpl<OpenTsdbWriter>::GetDefaultEnableHa() const
{
	 return false; 
}

bool ObjectImpl<OpenTsdbWriter>::GetDefaultEnableGenericMetrics() const
{
	 return false; 
}

bool ObjectImpl<OpenTsdbWriter>::GetDefaultConnected() const
{
	return bool();
}

bool ObjectImpl<OpenTsdbWriter>::GetDefaultShouldConnect() const
{
	 return true; 
}


boost::signals2::signal<void (const intrusive_ptr<OpenTsdbWriter>&, const Value&)> ObjectImpl<OpenTsdbWriter>::OnHostChanged;


boost::signals2::signal<void (const intrusive_ptr<OpenTsdbWriter>&, const Value&)> ObjectImpl<OpenTsdbWriter>::OnPortChanged;


boost::signals2::signal<void (const intrusive_ptr<OpenTsdbWriter>&, const Value&)> ObjectImpl<OpenTsdbWriter>::OnDisconnectTimeoutChanged;


boost::signals2::signal<void (const intrusive_ptr<OpenTsdbWriter>&, const Value&)> ObjectImpl<OpenTsdbWriter>::OnHostTemplateChanged;


boost::signals2::signal<void (const intrusive_ptr<OpenTsdbWriter>&, const Value&)> ObjectImpl<OpenTsdbWriter>::OnServiceTemplateChanged;


boost::signals2::signal<void (const intrusive_ptr<OpenTsdbWriter>&, const Value&)> ObjectImpl<OpenTsdbWriter>::OnEnableHaChanged;


boost::signals2::signal<void (const intrusive_ptr<OpenTsdbWriter>&, const Value&)> ObjectImpl<OpenTsdbWriter>::OnEnableGenericMetricsChanged;


boost::signals2::signal<void (const intrusive_ptr<OpenTsdbWriter>&, const Value&)> ObjectImpl<OpenTsdbWriter>::OnConnectedChanged;


boost::signals2::signal<void (const intrusive_ptr<OpenTsdbWriter>&, const Value&)> ObjectImpl<OpenTsdbWriter>::OnShouldConnectChanged;

static void TIValidateOpenTsdbWriter_1_2(const intrusive_ptr<ObjectImpl<OpenTsdbWriter> >& object, const String& key, const Value& value, std::vector<String>& location, const ValidationUtils& utils)
{
	bool known_attribute = false;
	do {
		known_attribute = true;
		if (value.IsEmpty() || value.IsScalar())
			return;
	} while (0);

	if (!known_attribute)
		BOOST_THROW_EXCEPTION(ValidationError(dynamic_pointer_cast<ConfigObject>(object), location, "Invalid attribute: " + key));
	else
		BOOST_THROW_EXCEPTION(ValidationError(dynamic_pointer_cast<ConfigObject>(object), location, "Invalid type."));
}

static void TIValidateOpenTsdbWriter_1(const intrusive_ptr<ObjectImpl<OpenTsdbWriter> >& object, const String& key, const Value& value, std::vector<String>& location, const ValidationUtils& utils)
{
	bool known_attribute = false;
	do {
		if (key != "metric")
			break;
		known_attribute = true;
		if (value.IsEmpty() || value.IsScalar())
			return;
	} while (0);

	do {
		if (key != "tags")
			break;
		known_attribute = true;
		if (value.IsObjectType<Dictionary>()) {
			Dictionary::Ptr dict = value;
			{
				ObjectLock olock(dict);
				for (const Dictionary::Pair& kv : dict) {
					const String& akey = kv.first;
					const Value& avalue = kv.second;
					location.emplace_back(akey);
					TIValidateOpenTsdbWriter_1_2(object, akey, avalue, location, utils);
					location.pop_back();
				}
			}
			return;
		}
	} while (0);

	if (!known_attribute)
		BOOST_THROW_EXCEPTION(ValidationError(dynamic_pointer_cast<ConfigObject>(object), location, "Invalid attribute: " + key));
	else
		BOOST_THROW_EXCEPTION(ValidationError(dynamic_pointer_cast<ConfigObject>(object), location, "Invalid type."));
}

static void TIValidateOpenTsdbWriter_2_2(const intrusive_ptr<ObjectImpl<OpenTsdbWriter> >& object, const String& key, const Value& value, std::vector<String>& location, const ValidationUtils& utils)
{
	bool known_attribute = false;
	do {
		known_attribute = true;
		if (value.IsEmpty() || value.IsScalar())
			return;
	} while (0);

	if (!known_attribute)
		BOOST_THROW_EXCEPTION(ValidationError(dynamic_pointer_cast<ConfigObject>(object), location, "Invalid attribute: " + key));
	else
		BOOST_THROW_EXCEPTION(ValidationError(dynamic_pointer_cast<ConfigObject>(object), location, "Invalid type."));
}

static void TIValidateOpenTsdbWriter_2(const intrusive_ptr<ObjectImpl<OpenTsdbWriter> >& object, const String& key, const Value& value, std::vector<String>& location, const ValidationUtils& utils)
{
	bool known_attribute = false;
	do {
		if (key != "metric")
			break;
		known_attribute = true;
		if (value.IsEmpty() || value.IsScalar())
			return;
	} while (0);

	do {
		if (key != "tags")
			break;
		known_attribute = true;
		if (value.IsObjectType<Dictionary>()) {
			Dictionary::Ptr dict = value;
			{
				ObjectLock olock(dict);
				for (const Dictionary::Pair& kv : dict) {
					const String& akey = kv.first;
					const Value& avalue = kv.second;
					location.emplace_back(akey);
					TIValidateOpenTsdbWriter_2_2(object, akey, avalue, location, utils);
					location.pop_back();
				}
			}
			return;
		}
	} while (0);

	if (!known_attribute)
		BOOST_THROW_EXCEPTION(ValidationError(dynamic_pointer_cast<ConfigObject>(object), location, "Invalid attribute: " + key));
	else
		BOOST_THROW_EXCEPTION(ValidationError(dynamic_pointer_cast<ConfigObject>(object), location, "Invalid type."));
}

static void TIValidateOpenTsdbWriterConnected(const intrusive_ptr<ObjectImpl<OpenTsdbWriter> >& object, bool value, std::vector<String>& location, const ValidationUtils& utils)
{
	if (!value)
		return;

}

static void TIValidateOpenTsdbWriterDisconnectTimeout(const intrusive_ptr<ObjectImpl<OpenTsdbWriter> >& object, double value, std::vector<String>& location, const ValidationUtils& utils)
{
}

static void TIValidateOpenTsdbWriterEnableGenericMetrics(const intrusive_ptr<ObjectImpl<OpenTsdbWriter> >& object, bool value, std::vector<String>& location, const ValidationUtils& utils)
{
	if (!value)
		return;

}

static void TIValidateOpenTsdbWriterEnableHa(const intrusive_ptr<ObjectImpl<OpenTsdbWriter> >& object, bool value, std::vector<String>& location, const ValidationUtils& utils)
{
	if (!value)
		return;

}

static void TIValidateOpenTsdbWriterHost(const intrusive_ptr<ObjectImpl<OpenTsdbWriter> >& object, const String& value, std::vector<String>& location, const ValidationUtils& utils)
{
	if (value.IsEmpty())
		return;

}

static void TIValidateOpenTsdbWriterHostTemplate(const intrusive_ptr<ObjectImpl<OpenTsdbWriter> >& object, const Dictionary::Ptr& value, std::vector<String>& location, const ValidationUtils& utils)
{
	if (!value)
		return;

	do {
		const Dictionary::Ptr& dict = value;
		{
			ObjectLock olock(dict);
			for (const Dictionary::Pair& kv : dict) {
				const String& akey = kv.first;
				const Value& avalue = kv.second;
				location.emplace_back(akey);
				TIValidateOpenTsdbWriter_1(object, akey, avalue, location, utils);
				location.pop_back();
			}
		}
		return;
	} while (0);

}

static void TIValidateOpenTsdbWriterPort(const intrusive_ptr<ObjectImpl<OpenTsdbWriter> >& object, const String& value, std::vector<String>& location, const ValidationUtils& utils)
{
	if (value.IsEmpty())
		return;

}

static void TIValidateOpenTsdbWriterServiceTemplate(const intrusive_ptr<ObjectImpl<OpenTsdbWriter> >& object, const Dictionary::Ptr& value, std::vector<String>& location, const ValidationUtils& utils)
{
	if (!value)
		return;

	do {
		const Dictionary::Ptr& dict = value;
		{
			ObjectLock olock(dict);
			for (const Dictionary::Pair& kv : dict) {
				const String& akey = kv.first;
				const Value& avalue = kv.second;
				location.emplace_back(akey);
				TIValidateOpenTsdbWriter_2(object, akey, avalue, location, utils);
				location.pop_back();
			}
		}
		return;
	} while (0);

}

static void TIValidateOpenTsdbWriterShouldConnect(const intrusive_ptr<ObjectImpl<OpenTsdbWriter> >& object, bool value, std::vector<String>& location, const ValidationUtils& utils)
{
	if (!value)
		return;

}

void ObjectImpl<OpenTsdbWriter>::ValidateConnected(const Lazy<bool>& lvalue, const ValidationUtils& utils)
{
	SimpleValidateConnected(lvalue, utils);
	std::vector<String> location;
	location.emplace_back("connected");
	TIValidateOpenTsdbWriterConnected(this, lvalue(), location, utils);
	location.pop_back();
}

void ObjectImpl<OpenTsdbWriter>::ValidateDisconnectTimeout(const Lazy<double>& lvalue, const ValidationUtils& utils)
{
	SimpleValidateDisconnectTimeout(lvalue, utils);
	std::vector<String> location;
	location.emplace_back("disconnect_timeout");
	TIValidateOpenTsdbWriterDisconnectTimeout(this, lvalue(), location, utils);
	location.pop_back();
}

void ObjectImpl<OpenTsdbWriter>::ValidateEnableGenericMetrics(const Lazy<bool>& lvalue, const ValidationUtils& utils)
{
	SimpleValidateEnableGenericMetrics(lvalue, utils);
	std::vector<String> location;
	location.emplace_back("enable_generic_metrics");
	TIValidateOpenTsdbWriterEnableGenericMetrics(this, lvalue(), location, utils);
	location.pop_back();
}

void ObjectImpl<OpenTsdbWriter>::ValidateEnableHa(const Lazy<bool>& lvalue, const ValidationUtils& utils)
{
	SimpleValidateEnableHa(lvalue, utils);
	std::vector<String> location;
	location.emplace_back("enable_ha");
	TIValidateOpenTsdbWriterEnableHa(this, lvalue(), location, utils);
	location.pop_back();
}

void ObjectImpl<OpenTsdbWriter>::ValidateHost(const Lazy<String>& lvalue, const ValidationUtils& utils)
{
	SimpleValidateHost(lvalue, utils);
	std::vector<String> location;
	location.emplace_back("host");
	TIValidateOpenTsdbWriterHost(this, lvalue(), location, utils);
	location.pop_back();
}

void ObjectImpl<OpenTsdbWriter>::ValidateHostTemplate(const Lazy<Dictionary::Ptr>& lvalue, const ValidationUtils& utils)
{
	SimpleValidateHostTemplate(lvalue, utils);
	std::vector<String> location;
	location.emplace_back("host_template");
	TIValidateOpenTsdbWriterHostTemplate(this, lvalue(), location, utils);
	location.pop_back();
}

void ObjectImpl<OpenTsdbWriter>::ValidatePort(const Lazy<String>& lvalue, const ValidationUtils& utils)
{
	SimpleValidatePort(lvalue, utils);
	std::vector<String> location;
	location.emplace_back("port");
	TIValidateOpenTsdbWriterPort(this, lvalue(), location, utils);
	location.pop_back();
}

void ObjectImpl<OpenTsdbWriter>::ValidateServiceTemplate(const Lazy<Dictionary::Ptr>& lvalue, const ValidationUtils& utils)
{
	SimpleValidateServiceTemplate(lvalue, utils);
	std::vector<String> location;
	location.emplace_back("service_template");
	TIValidateOpenTsdbWriterServiceTemplate(this, lvalue(), location, utils);
	location.pop_back();
}

void ObjectImpl<OpenTsdbWriter>::ValidateShouldConnect(const Lazy<bool>& lvalue, const ValidationUtils& utils)
{
	SimpleValidateShouldConnect(lvalue, utils);
	std::vector<String> location;
	location.emplace_back("should_connect");
	TIValidateOpenTsdbWriterShouldConnect(this, lvalue(), location, utils);
	location.pop_back();
}

}
#pragma GCC diagnostic pop
