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)); } }
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); } }
/** * 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; } }
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; }
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); }
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); } } }
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; }
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); }
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); }
/** * 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; } }
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(); }
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; }
/** * 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; }
/** * 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; }