String ConfigObjectUtility::CreateObjectConfig(const Type::Ptr& type, const String& fullName,
    bool ignoreOnError, const Array::Ptr& templates, const Dictionary::Ptr& attrs)
{
	NameComposer *nc = dynamic_cast<NameComposer *>(type.get());
	Dictionary::Ptr nameParts;
	String name;

	if (nc) {
		nameParts = nc->ParseName(fullName);
		name = nameParts->Get("name");
	} else
		name = fullName;

	Dictionary::Ptr allAttrs = new Dictionary();

	if (attrs) {
		attrs->CopyTo(allAttrs);

		ObjectLock olock(attrs);
		BOOST_FOREACH(const Dictionary::Pair& kv, attrs) {
			int fid = type->GetFieldId(kv.first.SubStr(0, kv.first.FindFirstOf(".")));

			if (fid < 0)
				BOOST_THROW_EXCEPTION(ScriptError("Invalid attribute specified: " + kv.first));

			Field field = type->GetFieldInfo(fid);

			if (!(field.Attributes & FAConfig) || kv.first == "name")
				BOOST_THROW_EXCEPTION(ScriptError("Attribute is marked for internal use only and may not be set: " + kv.first));
		}
	}
Example #2
0
bool ConfigObjectUtility::CreateObject(const Type::Ptr& type, const String& fullName,
    const Array::Ptr& templates, const Dictionary::Ptr& attrs, const Array::Ptr& errors)
{
	NameComposer *nc = dynamic_cast<NameComposer *>(type.get());
	Dictionary::Ptr nameParts;
	String name;

	if (nc) {
		nameParts = nc->ParseName(fullName);
		name = nameParts->Get("name");
	} else
		name = fullName;

	ConfigItemBuilder::Ptr builder = new ConfigItemBuilder();
	builder->SetType(type->GetName());
	builder->SetName(name);
	builder->SetScope(ScriptGlobal::GetGlobals());
	builder->SetPackage("_api");

	if (templates) {
		ObjectLock olock(templates);
		BOOST_FOREACH(const String& tmpl, templates) {
			ImportExpression *expr = new ImportExpression(MakeLiteral(tmpl));
			builder->AddExpression(expr);
		}
	}
Example #3
0
/**
 * Registers the configuration item.
 */
void ConfigItem::Register(void)
{
	Type::Ptr type = Type::GetByName(m_Type);

	m_ActivationContext = ActivationContext::GetCurrentContext();

	boost::mutex::scoped_lock lock(m_Mutex);

	/* If this is a non-abstract object with a composite name
	 * we register it in m_UnnamedItems instead of m_Items. */
	if (!m_Abstract && dynamic_cast<NameComposer *>(type.get()))
		m_UnnamedItems.push_back(this);
	else {
		ItemMap::const_iterator it = m_Items[m_Type].find(m_Name);

		if (it != m_Items[m_Type].end()) {
			std::ostringstream msgbuf;
			msgbuf << "A configuration item of type '" << GetType()
			       << "' and name '" << GetName() << "' already exists ("
			       << it->second->GetDebugInfo() << "), new declaration: " << GetDebugInfo();
			BOOST_THROW_EXCEPTION(ScriptError(msgbuf.str()));
		}

		m_Items[m_Type][m_Name] = this;
	}
}
Example #4
0
bool Type::IsAssignableFrom(const Type::Ptr& other) const
{
	for (Type::Ptr t = other; t; t = t->GetBaseType()) {
		if (t.get() == this)
			return true;
	}

	return false;
}
Example #5
0
ConfigObject::Ptr ConfigObject::GetObject(const String& type, const String& name)
{
	Type::Ptr ptype = Type::GetByName(type);
	auto *ctype = dynamic_cast<ConfigType *>(ptype.get());

	if (!ctype)
		return nullptr;

	return ctype->GetObject(name);
}
Example #6
0
void ConfigObjectTargetProvider::FindTargets(const String& type, const std::function<void (const Value&)>& addTarget) const
{
	Type::Ptr ptype = Type::GetByName(type);
	auto *ctype = dynamic_cast<ConfigType *>(ptype.get());

	if (ctype) {
		for (const ConfigObject::Ptr& object : ctype->GetObjects()) {
			addTarget(object);
		}
	}
}
Example #7
0
	bool ValidateName(const String& type, const String& name) const override
	{
		Type::Ptr ptype = Type::GetByName(type);
		auto *dtype = dynamic_cast<ConfigType *>(ptype.get());

		if (!dtype)
			return false;

		if (!dtype->GetObject(name))
			return false;

		return true;
	}
Example #8
0
void ConfigObject::OnAllConfigLoaded()
{
	static ConfigType *ctype;

	if (!ctype) {
		Type::Ptr type = Type::GetByName("Zone");
		ctype = dynamic_cast<ConfigType *>(type.get());
	}

	String zoneName = GetZoneName();

	if (!zoneName.IsEmpty())
		m_Zone = ctype->GetObject(zoneName);
}
Example #9
0
ConfigObject::Ptr ScriptUtils::GetObject(const Value& vtype, const String& name)
{
	Type::Ptr ptype;

	if (vtype.IsObjectType<Type>())
		ptype = vtype;
	else
		ptype = Type::GetByName(vtype);

	ConfigType *ctype = dynamic_cast<ConfigType *>(ptype.get());

	if (!ctype)
		return ConfigObject::Ptr();

	return ctype->GetObject(name);
}
Example #10
0
/**
 * Registers the configuration item.
 */
void ConfigItem::Register(void)
{
	Type::Ptr type = Type::GetByName(m_Type);

	/* If this is a non-abstract object with a composite name
	 * we register it in m_UnnamedItems instead of m_Items. */
	if (!m_Abstract && dynamic_cast<NameComposer *>(type.get())) {
		boost::mutex::scoped_lock lock(m_Mutex);
		m_UnnamedItems.push_back(this);
	} else {
		std::pair<String, String> key = std::make_pair(m_Type, m_Name);

		boost::mutex::scoped_lock lock(m_Mutex);
		m_Items[key] = this;
	}
}
Example #11
0
Array::Ptr ScriptUtils::GetObjects(const Type::Ptr& type)
{
	if (!type)
		BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid type: Must not be null"));

	ConfigType *ctype = dynamic_cast<ConfigType *>(type.get());

	if (!ctype)
		BOOST_THROW_EXCEPTION(std::invalid_argument("Invalid type: Type must inherit from 'ConfigObject'"));

	Array::Ptr result = new Array();

	for (const ConfigObject::Ptr& object : ctype->GetObjects())
		result->Add(object);

	return result;
}
String ConfigObjectUtility::CreateObjectConfig(const Type::Ptr& type, const String& fullName,
    bool ignoreOnError, const Array::Ptr& templates, const Dictionary::Ptr& attrs)
{
	NameComposer *nc = dynamic_cast<NameComposer *>(type.get());
	Dictionary::Ptr nameParts;
	String name;

	if (nc) {
		nameParts = nc->ParseName(fullName);
		name = nameParts->Get("name");
	} else
		name = fullName;

	Dictionary::Ptr allAttrs = new Dictionary();

	if (attrs) {
		attrs->CopyTo(allAttrs);

		ObjectLock olock(attrs);
		for (const Dictionary::Pair& kv : attrs) {
			int fid = type->GetFieldId(kv.first.SubStr(0, kv.first.FindFirstOf(".")));

			if (fid < 0)
				BOOST_THROW_EXCEPTION(ScriptError("Invalid attribute specified: " + kv.first));

			Field field = type->GetFieldInfo(fid);

			if (!(field.Attributes & FAConfig) || kv.first == "name")
				BOOST_THROW_EXCEPTION(ScriptError("Attribute is marked for internal use only and may not be set: " + kv.first));
		}
	}

	if (nameParts)
		nameParts->CopyTo(allAttrs);

	allAttrs->Remove("name");

	/* update the version for config sync */
	allAttrs->Set("version", Utility::GetTime());

	std::ostringstream config;
	ConfigWriter::EmitConfigItem(config, type->GetName(), name, false, ignoreOnError, templates, allAttrs);
	ConfigWriter::EmitRaw(config, "\n");

	return config.str();
}
Example #13
0
	static inline Value NewObject(ScriptFrame& frame, bool abstract, const String& type, const String& name, const boost::shared_ptr<Expression>& filter,
		const String& zone, std::map<String, Expression *> *closedVars, const boost::shared_ptr<Expression>& expression, const DebugInfo& debugInfo = DebugInfo())
	{
		ConfigItemBuilder::Ptr item = new ConfigItemBuilder(debugInfo);

		String checkName = name;

		if (!abstract) {
			Type::Ptr ptype = Type::GetByName(type);

			NameComposer *nc = dynamic_cast<NameComposer *>(ptype.get());

			if (nc)
				checkName = nc->MakeName(name, Dictionary::Ptr());
		}

		if (!checkName.IsEmpty()) {
			ConfigItem::Ptr oldItem = ConfigItem::GetObject(type, checkName);

			if (oldItem) {
				std::ostringstream msgbuf;
				msgbuf << "Object '" << name << "' of type '" << type << "' re-defined: " << debugInfo << "; previous definition: " << oldItem->GetDebugInfo();
				BOOST_THROW_EXCEPTION(ScriptError(msgbuf.str(), debugInfo));
			}
		}

		item->SetType(type);

		if (name.FindFirstOf("!") != String::NPos) {
			std::ostringstream msgbuf;
			msgbuf << "Name for object '" << name << "' of type '" << type << "' is invalid: Object names may not contain '!'";
			BOOST_THROW_EXCEPTION(ScriptError(msgbuf.str(), debugInfo));
		}

		item->SetName(name);

		item->AddExpression(new OwnedExpression(expression));
		item->SetAbstract(abstract);
		item->SetScope(EvaluateClosedVars(frame, closedVars));
		item->SetZone(zone);
		item->SetFilter(filter);
		item->Compile()->Register();

		return Empty;
	}
Example #14
0
/**
 * Commits the configuration item by creating a ConfigObject
 * object.
 *
 * @returns The ConfigObject that was created/updated.
 */
ConfigObject::Ptr ConfigItem::Commit(bool discard)
{
#ifdef I2_DEBUG
	Log(LogDebug, "ConfigItem")
	    << "Commit called for ConfigItem Type=" << GetType() << ", Name=" << GetName();
#endif /* I2_DEBUG */

	/* Make sure the type is valid. */
	Type::Ptr type = Type::GetByName(GetType());
	ASSERT(type && ConfigObject::TypeInstance->IsAssignableFrom(type));

	if (IsAbstract())
		return ConfigObject::Ptr();

	ConfigObject::Ptr dobj = static_pointer_cast<ConfigObject>(type->Instantiate());

	dobj->SetDebugInfo(m_DebugInfo);
	dobj->SetZoneName(m_Zone);
	dobj->SetPackage(m_Package);
	dobj->SetName(m_Name);

	DebugHint debugHints;

	ScriptFrame frame(dobj);
	if (m_Scope)
		m_Scope->CopyTo(frame.Locals);
	try {
		m_Expression->Evaluate(frame, &debugHints);
	} catch (const std::exception& ex) {
		if (m_IgnoreOnError) {
			Log(LogWarning, "ConfigObject")
			    << "Ignoring config object '" << m_Name << "' of type '" << m_Type << "' due to errors: " << DiagnosticInformation(ex);

			return ConfigObject::Ptr();
		}

		throw;
	}

	if (discard)
		m_Expression.reset();

	String item_name;
	String short_name = dobj->GetShortName();

	if (!short_name.IsEmpty()) {
		item_name = short_name;
		dobj->SetName(short_name);
	} else
		item_name = m_Name;

	String name = item_name;

	NameComposer *nc = dynamic_cast<NameComposer *>(type.get());

	if (nc) {
		name = nc->MakeName(name, dobj);

		if (name.IsEmpty())
			BOOST_THROW_EXCEPTION(std::runtime_error("Could not determine name for object"));
	}

	if (name != item_name)
		dobj->SetShortName(item_name);

	dobj->SetName(name);

	try {
		dobj->OnConfigLoaded();
	} catch (const std::exception& ex) {
		if (m_IgnoreOnError) {
			Log(LogWarning, "ConfigObject")
			    << "Ignoring config object '" << m_Name << "' of type '" << m_Type << "' due to errors: " << DiagnosticInformation(ex);

			return ConfigObject::Ptr();
		}

		throw;
	}

	Dictionary::Ptr persistentItem = new Dictionary();

	persistentItem->Set("type", GetType());
	persistentItem->Set("name", GetName());
	persistentItem->Set("properties", Serialize(dobj, FAConfig));

	Dictionary::Ptr dhint = debugHints.ToDictionary();
	persistentItem->Set("debug_hints", dhint);

	Array::Ptr di = new Array();
	di->Add(m_DebugInfo.Path);
	di->Add(m_DebugInfo.FirstLine);
	di->Add(m_DebugInfo.FirstColumn);
	di->Add(m_DebugInfo.LastLine);
	di->Add(m_DebugInfo.LastColumn);
	persistentItem->Set("debug_info", di);

	try {
		DefaultValidationUtils utils;
		dobj->Validate(FAConfig, utils);
	} catch (ValidationError& ex) {
		if (m_IgnoreOnError) {
			Log(LogWarning, "ConfigObject")
			    << "Ignoring config object '" << m_Name << "' of type '" << m_Type << "' due to errors: " << DiagnosticInformation(ex);

			return ConfigObject::Ptr();
		}

		ex.SetDebugHint(dhint);
		throw;
	}

	ConfigCompilerContext::GetInstance()->WriteObject(persistentItem);
	persistentItem.reset();

	dhint.reset();

	dobj->Register();

	m_Object = dobj;

	return dobj;
}
Example #15
0
/**
 * Commits the configuration item by creating a DynamicObject
 * object.
 *
 * @returns The DynamicObject that was created/updated.
 */
DynamicObject::Ptr ConfigItem::Commit(bool discard)
{
	ASSERT(!OwnsLock());

#ifdef _DEBUG
	Log(LogDebug, "ConfigItem")
	    << "Commit called for ConfigItem Type=" << GetType() << ", Name=" << GetName();
#endif /* _DEBUG */

	/* Make sure the type is valid. */
	Type::Ptr type = Type::GetByName(GetType());
	ASSERT(type && Type::GetByName("DynamicObject")->IsAssignableFrom(type));

	if (IsAbstract())
		return DynamicObject::Ptr();

	DynamicObject::Ptr dobj = static_pointer_cast<DynamicObject>(type->Instantiate());

	dobj->SetDebugInfo(m_DebugInfo);
	dobj->SetTypeName(m_Type);
	dobj->SetZone(m_Zone);

	Dictionary::Ptr locals = new Dictionary();
	locals->Set("__parent", m_Scope);
	m_Scope.reset();

	dobj->SetParentScope(locals);
	locals.reset();

	dobj->SetName(m_Name);

	DebugHint debugHints;

	try {
		m_Expression->Evaluate(dobj, &debugHints);
	} catch (const ConfigError& ex) {
		const DebugInfo *di = boost::get_error_info<errinfo_debuginfo>(ex);
		ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), di ? *di : DebugInfo());
	} catch (const std::exception& ex) {
		ConfigCompilerContext::GetInstance()->AddMessage(true, DiagnosticInformation(ex));
	}

	if (discard)
		m_Expression.reset();

	dobj->SetParentScope(Object::Ptr());

	String name = m_Name;

	NameComposer *nc = dynamic_cast<NameComposer *>(type.get());

	if (nc) {
		name = nc->MakeName(m_Name, dobj);

		if (name.IsEmpty())
			BOOST_THROW_EXCEPTION(std::runtime_error("Could not determine name for object"));
	}

	if (name != m_Name)
		dobj->SetShortName(m_Name);

	dobj->SetName(name);

	Dictionary::Ptr attrs = Serialize(dobj, FAConfig);

	Dictionary::Ptr persistentItem = new Dictionary();

	persistentItem->Set("type", GetType());
	persistentItem->Set("name", GetName());
	persistentItem->Set("properties", attrs);
	persistentItem->Set("debug_hints", debugHints.ToDictionary());

	ConfigCompilerContext::GetInstance()->WriteObject(persistentItem);
	persistentItem.reset();

	ConfigType::Ptr ctype = ConfigType::GetByName(GetType());

	if (!ctype)
		ConfigCompilerContext::GetInstance()->AddMessage(false, "No validation type found for object '" + GetName() + "' of type '" + GetType() + "'");
	else {
		TypeRuleUtilities utils;

		try {
			attrs->Remove("name");
			ctype->ValidateItem(GetName(), attrs, GetDebugInfo(), &utils);
		} catch (const ConfigError& ex) {
			const DebugInfo *di = boost::get_error_info<errinfo_debuginfo>(ex);
			ConfigCompilerContext::GetInstance()->AddMessage(true, ex.what(), di ? *di : DebugInfo());
		} catch (const std::exception& ex) {
			ConfigCompilerContext::GetInstance()->AddMessage(true, DiagnosticInformation(ex));
		}
	}

	dobj->Register();

	m_Object = dobj;

	return dobj;
}