BOOST_THROW_EXCEPTION(std::runtime_error("Invalid field ID."));
}
+Object::Ptr Object::NavigateField(int id) const
+{
+ BOOST_THROW_EXCEPTION(std::runtime_error("Invalid field ID."));
+}
+
Object::Ptr Object::Clone(void) const
{
BOOST_THROW_EXCEPTION(std::runtime_error("Object cannot be cloned."));
virtual Value GetField(int id) const;
virtual void ValidateField(int id, const Value& value, const ValidationUtils& utils);
virtual void NotifyField(int id, const Value& cookie = Empty);
+ virtual Object::Ptr NavigateField(int id) const;
#ifdef I2_DEBUG
bool OwnsLock(void) const;
return GetBaseType()->GetFieldInfo(id);
if (id == 0)
- return Field(0, "String", "name", NULL, 0, 0);
+ return Field(0, "String", "name", "", NULL, 0, 0);
else if (id == 1)
- return Field(1, "Object", "prototype", NULL, 0, 0);
+ return Field(1, "Object", "prototype", "", NULL, 0, 0);
else if (id == 2)
- return Field(2, "Type", "base", NULL, 0, 0);
+ return Field(2, "Type", "base", "", NULL, 0, 0);
throw std::runtime_error("Invalid field ID.");
}
FAConfig = 2,
FAState = 4,
FAInternal = 64,
- FARequired = 512
-};
+ FARequired = 512,
+ FANavigation = 1024
+};
class Type;
int ID;
const char *TypeName;
const char *Name;
+ const char *NavigationName;
const char *RefTypeName;
int Attributes;
int ArrayRank;
- Field(int id, const char *type, const char *name, const char *reftype, int attributes, int arrayRank)
- : ID(id), TypeName(type), Name(name), RefTypeName(reftype), Attributes(attributes), ArrayRank(arrayRank)
+ Field(int id, const char *type, const char *name, const char *navigationName, const char *reftype, int attributes, int arrayRank)
+ : ID(id), TypeName(type), Name(name), NavigationName(navigationName), RefTypeName(reftype), Attributes(attributes), ArrayRank(arrayRank)
{ }
};
CheckCommand::Ptr Checkable::GetCheckCommand(void) const
{
- return CheckCommand::GetByName(GetCheckCommandRaw());
+ return dynamic_pointer_cast<CheckCommand>(NavigateCheckCommandRaw());
}
TimePeriod::Ptr Checkable::GetCheckPeriod(void) const
#include "icinga/icingaapplication.hpp"
#include "icinga/customvarobject.hpp"
#include "base/array.hpp"
+#impl_include "icinga/checkcommand.hpp"
+#impl_include "icinga/eventcommand.hpp"
library icinga;
abstract class Checkable : CustomVarObject
{
- [config, required] name(CheckCommand) check_command (CheckCommandRaw);
+ [config, required, navigation] name(CheckCommand) check_command (CheckCommandRaw) {
+ navigate {{{
+ return CheckCommand::GetByName(GetCheckCommandRaw());
+ }}}
+ };
[config] int max_check_attempts {
default {{{ return 3; }}}
};
- [config] name(TimePeriod) check_period (CheckPeriodRaw);
+ [config, navigation] name(TimePeriod) check_period (CheckPeriodRaw) {
+ navigate {{{
+ return TimePeriod::GetByName(GetCheckPeriodRaw());
+ }}}
+ };
[config] double check_interval {
default {{{ return 5 * 60; }}}
};
[config] double retry_interval {
default {{{ return 60; }}}
};
- [config] name(EventCommand) event_command (EventCommandRaw);
+ [config, navigation] name(EventCommand) event_command (EventCommandRaw) {
+ navigate {{{
+ return EventCommand::GetByName(GetEventCommandRaw());
+ }}}
+ };
[config] bool volatile;
[config] double flapping_threshold {
default {{{ return 30; }}}
get {{{ return false; }}}
};
- [config] name(Endpoint) command_endpoint (CommandEndpointRaw);
+ [config, navigation] name(Endpoint) command_endpoint (CommandEndpointRaw) {
+ navigate {{{
+ return Endpoint::GetByName(GetCommandEndpointRaw());
+ }}}
+ };
};
}
load_after Host;
load_after Service;
- [config, required] name(Host) child_host_name;
- [config] String child_service_name {
+ [config, required, navigation(child_host)] name(Host) child_host_name {
+ navigate {{{
+ return Host::GetByName(GetChildHostName());
+ }}}
+ };
+
+ [config, navigation(child_service)] String child_service_name {
track {{{
if (!oldValue.IsEmpty()) {
Service::Ptr service = Service::GetByNamePair(GetParentHostName(), oldValue);
DependencyGraph::RemoveDependency(this, service.get());
}
}}}
+ navigate {{{
+ if (GetChildServiceName().IsEmpty())
+ return Service::Ptr();
+
+ Host::Ptr host = Host::GetByName(GetChildHostName());
+ return host->GetServiceByShortName(GetChildServiceName());
+ }}}
+ };
+
+ [config, required, navigation(parent_host)] name(Host) parent_host_name {
+ navigate {{{
+ return Host::GetByName(GetParentHostName());
+ }}}
};
- [config, required] name(Host) parent_host_name;
- [config] String parent_service_name {
+ [config, navigation(parent_service)] String parent_service_name {
track {{{
if (!oldValue.IsEmpty()) {
Service::Ptr service = Service::GetByNamePair(GetParentHostName(), oldValue);
DependencyGraph::RemoveDependency(this, service.get());
}
}}}
+ navigate {{{
+ if (GetParentServiceName().IsEmpty())
+ return Service::Ptr();
+
+ Host::Ptr host = Host::GetByName(GetParentHostName());
+ return host->GetServiceByShortName(GetParentServiceName());
+ }}}
};
- [config] name(TimePeriod) period (PeriodRaw);
+ [config, navigation] name(TimePeriod) period (PeriodRaw) {
+ navigate {{{
+ return TimePeriod::GetByName(GetPeriodRaw());
+ }}}
+ };
[config] array(double) states;
int state_filter_real (StateFilter);
******************************************************************************/
#include "icinga/customvarobject.hpp"
+#impl_include "icinga/notificationcommand.hpp"
#impl_include "icinga/service.hpp"
library icinga;
load_after Host;
load_after Service;
- [config, protected, required] name(NotificationCommand) command (CommandRaw);
+ [config, protected, required, navigation] name(NotificationCommand) command (CommandRaw) {
+ navigate {{{
+ return NotificationCommand::GetByName(GetCommandRaw());
+ }}}
+ };
[config] double interval {
default {{{ return 1800; }}}
};
- [config] name(TimePeriod) period (PeriodRaw);
+ [config, navigation] name(TimePeriod) period (PeriodRaw) {
+ navigate {{{
+ return TimePeriod::GetByName(GetPeriodRaw());
+ }}}
+ };
[config, protected] array(name(User)) users (UsersRaw);
[config, protected] array(name(UserGroup)) user_groups (UserGroupsRaw);
[config] Dictionary::Ptr times;
int type_filter_real (TypeFilter);
[config] array(double) states;
int state_filter_real (StateFilter);
- [config, protected, required] name(Host) host_name;
- [config, protected] String service_name {
+ [config, protected, required, navigation(host)] name(Host) host_name {
+ navigate {{{
+ return Host::GetByName(GetHostName());
+ }}}
+ };
+ [config, protected, navigation(service)] String service_name {
track {{{
if (!oldValue.IsEmpty()) {
Service::Ptr service = Service::GetByNamePair(GetHostName(), oldValue);
DependencyGraph::RemoveDependency(this, service.get());
}
}}}
+ navigate {{{
+ if (GetServiceName().IsEmpty())
+ return Service::Ptr();
+
+ Host::Ptr host = Host::GetByName(GetHostName());
+ return host->GetServiceByShortName(GetServiceName());
+ }}}
};
[state] Array::Ptr notified_users {
[state, set_protected] Value notification_number;
[state] double last_problem_notification;
- [config] name(Endpoint) command_endpoint (CommandEndpointRaw);
+ [config, navigation] name(Endpoint) command_endpoint (CommandEndpointRaw) {
+ navigate {{{
+ return Endpoint::GetByName(GetCommandEndpointRaw());
+ }}}
+ };
};
validator Notification {
load_after Host;
load_after Service;
- [config, protected, required] name(Host) host_name;
- [config, protected] String service_name {
+ [config, protected, required, navigation(host)] name(Host) host_name {
+ navigate {{{
+ return Host::GetByName(GetHostName());
+ }}}
+ };
+ [config, protected, navigation(service)] String service_name {
track {{{
if (!oldValue.IsEmpty()) {
Service::Ptr service = Service::GetByNamePair(GetHostName(), oldValue);
DependencyGraph::RemoveDependency(this, service.get());
}
}}}
+ navigate {{{
+ if (GetServiceName().IsEmpty())
+ return Service::Ptr();
+
+ Host::Ptr host = Host::GetByName(GetHostName());
+ return host->GetServiceByShortName(GetServiceName());
+ }}}
};
[config, required] String author;
static Service::Ptr GetByNamePair(const String& hostName, const String& serviceName);
- Host::Ptr GetHost(void) const;
+ virtual Host::Ptr GetHost(void) const override;
virtual bool ResolveMacro(const String& macro, const CheckResult::Ptr& cr, Value *result) const override;
}}}
};
[config, required] name(Host) host_name;
+ [no_storage, navigation] Host::Ptr host {
+ get;
+ navigate {{{
+ return GetHost();
+ }}}
+ };
[enum, no_storage] ServiceState "state" {
get {{{
return GetStateRaw();
[config] array(name(UserGroup)) groups {
default {{{ return new Array(); }}}
};
- [config] name(TimePeriod) period (PeriodRaw);
+ [config, navigation] name(TimePeriod) period (PeriodRaw) {
+ navigate {{{
+ return TimePeriod::GetByName(GetPeriodRaw());
+ }}}
+ };
+
[config] array(double) types;
int type_filter_real (TypeFilter);
[config] array(double) states;
return Type::GetByName(type)->GetPluralName();
}
-static void FilteredAddTarget(ScriptFrame& frame, const String& varName, Expression *ufilter, std::vector<Value>& result, const Value& target)
+static void FilteredAddTarget(ScriptFrame& frame, Expression *ufilter, std::vector<Value>& result, const Object::Ptr& target)
{
+ Type::Ptr type = target->GetReflectionType();
+ String varName = type->GetName();
+ boost::algorithm::to_lower(varName);
+
frame.Locals->Set(varName, target);
+ for (int fid = 0; fid < type->GetFieldCount(); fid++) {
+ Field field = type->GetFieldInfo(fid);
+
+ if ((field.Attributes & FANavigation) == 0)
+ continue;
+
+ Object::Ptr joinedObj = target->NavigateField(fid);
+
+ varName = field.TypeName;
+ boost::algorithm::to_lower(varName);
+
+ frame.Locals->Set(varName, joinedObj);
+ }
+
if (Convert::ToBool(ufilter->Evaluate(frame)))
result.push_back(target);
}
}
}
- String varName = type;
- boost::algorithm::to_lower(varName);
-
try {
- provider->FindTargets(type, boost::bind(&FilteredAddTarget, boost::ref(frame), varName, ufilter, boost::ref(result), _1));
+ provider->FindTargets(type, boost::bind(&FilteredAddTarget, boost::ref(frame), ufilter, boost::ref(result), _1));
} catch (const std::exception& ex) {
delete ufilter;
throw;
QueryDescription qd;
qd.Types.insert(type->GetName());
- std::vector<String> joinTypes;
- joinTypes.push_back(type->GetName());
+ std::vector<String> joinAttrs;
+ joinAttrs.push_back("");
+
+ for (int fid = 0; fid < type->GetFieldCount(); fid++) {
+ Field field = type->GetFieldInfo(fid);
+
+ if (field.Attributes & FANavigation)
+ joinAttrs.push_back(field.Name);
+ }
Dictionary::Ptr params = HttpUtility::FetchRequestParameters(request);
Dictionary::Ptr resultAttrs = new Dictionary();
result1->Set("attrs", resultAttrs);
- BOOST_FOREACH(const String& joinType, joinTypes) {
- String prefix = joinType;
- boost::algorithm::to_lower(prefix);
+ BOOST_FOREACH(const String& joinAttr, joinAttrs) {
+ Object::Ptr joinedObj;
+ String prefix;
+
+ if (joinAttr.IsEmpty()) {
+ joinedObj = obj;
+ prefix = type->GetName();
+ } else {
+ int fid = type->GetFieldId(joinAttr);
+ joinedObj = static_cast<Object::Ptr>(obj)->NavigateField(fid);
+
+ if (!joinedObj)
+ continue;
- for (int fid = 0; fid < type->GetFieldCount(); fid++) {
Field field = type->GetFieldInfo(fid);
+ prefix = field.NavigationName;
+ }
+
+ boost::algorithm::to_lower(prefix);
+
+ Type::Ptr joinedType = joinedObj->GetReflectionType();
+
+ for (int fid = 0; fid < joinedType->GetFieldCount(); fid++) {
+ Field field = joinedType->GetFieldInfo(fid);
String aname = prefix + "." + field.Name;
if (!attrs.empty() && attrs.find(aname) == attrs.end())
continue;
- Value val = static_cast<Object::Ptr>(obj)->GetField(fid);
+ Value val = joinedObj->GetField(fid);
+
+ /* hide internal navigation fields */
+ if (field.Attributes & FANavigation) {
+ Value nval = joinedObj->NavigateField(fid);
+
+ if (val == nval)
+ continue;
+ }
+
Value sval = Serialize(val, FAConfig | FAState);
resultAttrs->Set(aname, sval);
}
fieldInfo->Set("type", field.TypeName);
if (field.RefTypeName)
fieldInfo->Set("ref_type", field.RefTypeName);
+ if (field.Attributes & FANavigation)
+ fieldInfo->Set("navigation_name", field.NavigationName);
fieldInfo->Set("array_rank", field.ArrayRank);
Dictionary::Ptr attributeInfo = new Dictionary();
attributeInfo->Set("state", static_cast<bool>(field.Attributes & FAState));
attributeInfo->Set("internal", static_cast<bool>(field.Attributes & FAInternal));
attributeInfo->Set("required", static_cast<bool>(field.Attributes & FARequired));
-
+ attributeInfo->Set("navigation", static_cast<bool>(field.Attributes & FANavigation));
}
}
class Zone : ConfigObject
{
- [config] name(Zone) parent (ParentRaw);
+ [config, navigation] name(Zone) parent (ParentRaw) {
+ navigate {{{
+ return Zone::GetByName(GetParentRaw());
+ }}}
+ };
+
[config] array(name(Endpoint)) endpoints (EndpointsRaw);
[config] bool global;
};
protected { yylval->num = FAGetProtected | FASetProtected; return T_FIELD_ATTRIBUTE; }
internal { yylval->num = FAInternal; return T_FIELD_ATTRIBUTE; }
no_storage { yylval->num = FANoStorage; return T_FIELD_ATTRIBUTE; }
+navigation { return T_NAVIGATION; }
validator { return T_VALIDATOR; }
required { return T_REQUIRED; }
name { return T_NAME; }
get { yylval->num = FTGet; return T_FIELD_ACCESSOR_TYPE; }
set { yylval->num = FTSet; return T_FIELD_ACCESSOR_TYPE; }
track { yylval->num = FTTrack; return T_FIELD_ACCESSOR_TYPE; }
+navigate { yylval->num = FTNavigate; return T_FIELD_ACCESSOR_TYPE; }
\"[^\"]+\" { yylval->text = strdup(yytext + 1); yylval->text[strlen(yylval->text) - 1] = '\0'; return T_STRING; }
-\<[^>]+\> { yylval->text = strdup(yytext + 1); yylval->text[strlen(yylval->text) - 1] = '\0'; return T_ANGLE_STRING; }
+\<[^ \>]*\> { yylval->text = strdup(yytext + 1); yylval->text[strlen(yylval->text) - 1] = '\0'; return T_ANGLE_STRING; }
[a-zA-Z_][:a-zA-Z0-9\-_]* { yylval->text = strdup(yytext); return T_IDENTIFIER; }
. return yytext[0];
%token T_NAMESPACE "namespace (T_NAMESPACE)"
%token T_VALIDATOR "validator (T_VALIDATOR)"
%token T_REQUIRED "required (T_REQUIRED)"
+%token T_NAVIGATION "navigation (T_NAVIGATION)"
%token T_NAME "name (T_NAME)"
%token T_ARRAY "array (T_ARRAY)"
%token T_STRING "string (T_STRING)"
%type <text> angle_impl_include
%type <text> code
%type <num> T_FIELD_ATTRIBUTE
-%type <num> field_attribute
-%type <num> field_attributes
-%type <num> field_attribute_list
+%type <field> field_attribute
+%type <field> field_attributes
+%type <field> field_attribute_list
%type <num> T_FIELD_ACCESSOR_TYPE
%type <num> T_CLASS_ATTRIBUTE
%type <num> class_attribute_list
class_field: field_attribute_list field_type identifier alternative_name_specifier field_accessor_list ';'
{
- Field *field = new Field();
-
- field->Attributes = $1;
+ Field *field = $1;
if ((field->Attributes & (FAConfig | FAState)) == 0)
field->Attributes |= FAEphemeral;
case FTTrack:
field->TrackAccessor = it->Accessor;
break;
+ case FTNavigate:
+ field->NavigateAccessor = it->Accessor;
+ field->PureNavigateAccessor = it->Pure;
+ break;
}
}
field_attribute_list: /* empty */
{
- $$ = 0;
+ $$ = new Field();
}
| '[' field_attributes ']'
{
field_attribute: T_FIELD_ATTRIBUTE
{
- $$ = $1;
+ $$ = new Field();
+ $$->Attributes = $1;
}
| T_REQUIRED
{
- $$ = FARequired;
+ $$ = new Field();
+ $$->Attributes = FARequired;
+ }
+ | T_NAVIGATION '(' identifier ')'
+ {
+ $$ = new Field();
+ $$->Attributes = FANavigation;
+ $$->NavigationName = $3;
+ std::free($3);
+ }
+ | T_NAVIGATION
+ {
+ $$ = new Field();
+ $$->Attributes = FANavigation;
}
;
field_attributes: /* empty */
{
- $$ = 0;
+ $$ = new Field();
}
| field_attributes ',' field_attribute
{
- $$ = $1 | $3;
+ $$ = $1;
+ $$->Attributes |= $3->Attributes;
+ if (!$3->NavigationName.empty())
+ $$->NavigationName = $3->NavigationName;
+ delete $3;
}
| field_attribute
{
nameref = "NULL";
m_Impl << "\t\t" << "case " << num << ":" << std::endl
- << "\t\t\t" << "return Field(" << num << ", \"" << ftype << "\", \"" << it->Name << "\", " << nameref << ", " << it->Attributes << ", " << it->Type.ArrayRank << ");" << std::endl;
+ << "\t\t\t" << "return Field(" << num << ", \"" << ftype << "\", \"" << it->Name << "\", \"" << (it->NavigationName.empty() ? it->Name : it->NavigationName) << "\", " << nameref << ", " << it->Attributes << ", " << it->Type.ArrayRank << ");" << std::endl;
num++;
}
m_Impl << "}" << std::endl << std::endl;
+ /* NavigateField */
+ m_Header << "protected:" << std::endl
+ << "\t" << "virtual Object::Ptr NavigateField(int id) const override;" << std::endl;
+
+ m_Impl << "Object::Ptr ObjectImpl<" << klass.Name << ">::NavigateField(int id) const" << 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) { return " << klass.Parent << "::NavigateField(id); }" << std::endl;
+
+ m_Impl << "\t" << "switch (";
+
+ if (!klass.Parent.empty())
+ m_Impl << "real_id";
+ else
+ m_Impl << "id";
+
+ m_Impl << ") {" << std::endl;
+
+ num = 0;
+ for (it = klass.Fields.begin(); it != klass.Fields.end(); it++) {
+ if (it->Attributes & FANavigation) {
+ m_Impl << "\t\t" << "case " << num << ":" << std::endl
+ << "\t\t\t" << "return Navigate" << it->GetFriendlyName() << "();" << std::endl;
+ }
+
+ num++;
+ }
+
+ m_Impl << "\t\t" << "default:" << std::endl
+ << "\t\t\t" << "throw std::runtime_error(\"Invalid field ID.\");" << std::endl
+ << "\t" << "}" << std::endl;
+
+ m_Impl << "}" << std::endl << std::endl;
+
/* getters */
for (it = klass.Fields.begin(); it != klass.Fields.end(); it++) {
std::string prot;
m_Impl << "}" << std::endl << std::endl;
}
+ /* navigation */
+ for (it = klass.Fields.begin(); it != klass.Fields.end(); it++) {
+ if ((it->Attributes & FANavigation) == 0)
+ continue;
+
+ m_Header << "public:" << std::endl
+ << "\t" << "virtual Object::Ptr Navigate" << it->GetFriendlyName() << "(void) const";
+
+ if (it->PureNavigateAccessor) {
+ m_Header << " = 0;" << std::endl;
+ } else {
+ m_Header << ";" << std::endl;
+
+ m_Impl << "Object::Ptr ObjectImpl<" << klass.Name << ">::Navigate" << it->GetFriendlyName() << "(void) const" << std::endl
+ << "{" << std::endl;
+
+ if (it->NavigateAccessor.empty())
+ m_Impl << "\t" << "return Get" << it->GetFriendlyName() << "();" << std::endl;
+ else
+ m_Impl << "\t" << it->NavigateAccessor << std::endl;
+
+ m_Impl << "}" << std::endl << std::endl;
+ }
+ }
+
/* start/stop */
if (needs_tracking) {
m_Header << "virtual void Start(void) override;" << std::endl
FTGet,
FTSet,
FTDefault,
- FTTrack
+ FTTrack,
+ FTNavigate
};
struct FieldAccessor
FAInternal = 64,
FANoStorage = 128,
FALoadDependency = 256,
- FARequired = 512
+ FARequired = 512,
+ FANavigation = 1024
};
struct FieldType
bool PureSetAccessor;
std::string DefaultAccessor;
std::string TrackAccessor;
+ std::string NavigationName;
+ std::string NavigateAccessor;
+ bool PureNavigateAccessor;
Field(void)
- : Attributes(0), PureGetAccessor(false), PureSetAccessor(false)
+ : Attributes(0), PureGetAccessor(false), PureSetAccessor(false), PureNavigateAccessor(false)
{ }
inline std::string GetFriendlyName(void) const