]> granicus.if.org Git - icinga2/blob - lib/config/expression.cpp
Fix incorrect field name
[icinga2] / lib / config / expression.cpp
1 /******************************************************************************
2  * Icinga 2                                                                   *
3  * Copyright (C) 2012-2014 Icinga Development Team (http://www.icinga.org)    *
4  *                                                                            *
5  * This program is free software; you can redistribute it and/or              *
6  * modify it under the terms of the GNU General Public License                *
7  * as published by the Free Software Foundation; either version 2             *
8  * of the License, or (at your option) any later version.                     *
9  *                                                                            *
10  * This program is distributed in the hope that it will be useful,            *
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the              *
13  * GNU General Public License for more details.                               *
14  *                                                                            *
15  * You should have received a copy of the GNU General Public License          *
16  * along with this program; if not, write to the Free Software Foundation     *
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.             *
18  ******************************************************************************/
19
20 #include "config/expression.hpp"
21 #include "config/configitem.hpp"
22 #include "config/configitembuilder.hpp"
23 #include "config/applyrule.hpp"
24 #include "config/objectrule.hpp"
25 #include "base/array.hpp"
26 #include "base/json.hpp"
27 #include "base/scriptfunction.hpp"
28 #include "base/scriptvariable.hpp"
29 #include "base/utility.hpp"
30 #include "base/objectlock.hpp"
31 #include "base/object.hpp"
32 #include "base/logger.hpp"
33 #include "base/configerror.hpp"
34 #include <boost/foreach.hpp>
35 #include <boost/exception_ptr.hpp>
36 #include <boost/exception/errinfo_nested_exception.hpp>
37
38 using namespace icinga;
39
40 Expression::Expression(OpCallback op, const Value& operand1, const DebugInfo& di)
41         : m_Operator(op), m_Operand1(operand1), m_Operand2(), m_DebugInfo(di)
42 { }
43
44 Expression::Expression(OpCallback op, const Value& operand1, const Value& operand2, const DebugInfo& di)
45         : m_Operator(op), m_Operand1(operand1), m_Operand2(operand2), m_DebugInfo(di)
46 { }
47
48 Value Expression::Evaluate(const Dictionary::Ptr& locals, DebugHint *dhint) const
49 {
50         try {
51 #ifdef _DEBUG
52                 if (m_Operator != &Expression::OpLiteral) {
53                         std::ostringstream msgbuf;
54                         ShowCodeFragment(msgbuf, m_DebugInfo, false);
55                         Log(LogDebug, "Expression")
56                             << "Executing:\n" << msgbuf.str();
57                 }
58 #endif /* _DEBUG */
59
60                 return m_Operator(this, locals, dhint);
61         } catch (const std::exception& ex) {
62                 if (boost::get_error_info<boost::errinfo_nested_exception>(ex))
63                         throw;
64                 else
65                         BOOST_THROW_EXCEPTION(ConfigError("Error while evaluating expression: " + String(ex.what())) << boost::errinfo_nested_exception(boost::current_exception()) << errinfo_debuginfo(m_DebugInfo));
66         }
67 }
68
69 void Expression::MakeInline(void)
70 {
71         if (m_Operator == &Expression::OpDict)
72                 m_Operand2 = true;
73 }
74
75 void Expression::DumpOperand(std::ostream& stream, const Value& operand, int indent) {
76         if (operand.IsObjectType<Array>()) {
77                 Array::Ptr arr = operand;
78                 stream << String(indent, ' ') << "Array:\n";
79                 ObjectLock olock(arr);
80                 BOOST_FOREACH(const Value& elem, arr) {
81                         DumpOperand(stream, elem, indent + 1);
82                 }
83         } else if (operand.IsObjectType<Expression>()) {
84                 Expression::Ptr left = operand;
85                 left->Dump(stream, indent);
86         } else {
87                 stream << String(indent, ' ') << JsonEncode(operand) << "\n";
88         }
89 }
90
91 void Expression::Dump(std::ostream& stream, int indent) const
92 {
93         String sym = Utility::GetSymbolName(reinterpret_cast<const void *>(m_Operator));
94         stream << String(indent, ' ') << "op: " << Utility::DemangleSymbolName(sym) << "\n";
95         stream << String(indent, ' ') << "left:\n";
96         DumpOperand(stream, m_Operand1, indent + 1);
97         
98         stream << String(indent, ' ') << "right:\n";
99         DumpOperand(stream, m_Operand2, indent + 1);
100 }
101
102 Value Expression::EvaluateOperand1(const Dictionary::Ptr& locals, DebugHint *dhint) const
103 {
104         return static_cast<Expression::Ptr>(m_Operand1)->Evaluate(locals, dhint);
105 }
106
107 Value Expression::EvaluateOperand2(const Dictionary::Ptr& locals, DebugHint *dhint) const
108 {
109         return static_cast<Expression::Ptr>(m_Operand2)->Evaluate(locals, dhint);
110 }
111
112 Value Expression::OpLiteral(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint)
113 {
114         return expr->m_Operand1;
115 }
116
117 Value Expression::OpVariable(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint)
118 {
119         Dictionary::Ptr scope = locals;
120
121         while (scope) {
122                 if (scope->Contains(expr->m_Operand1))
123                         return scope->Get(expr->m_Operand1);
124
125                 scope = scope->Get("__parent");
126         }
127
128         return ScriptVariable::Get(expr->m_Operand1);
129 }
130
131 Value Expression::OpNegate(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint)
132 {
133         return ~(long)expr->EvaluateOperand1(locals);
134 }
135
136 Value Expression::OpLogicalNegate(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint)
137 {
138         return !expr->EvaluateOperand1(locals).ToBool();
139 }
140
141 Value Expression::OpAdd(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint)
142 {
143         return expr->EvaluateOperand1(locals) + expr->EvaluateOperand2(locals);
144 }
145
146 Value Expression::OpSubtract(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint)
147 {
148         return expr->EvaluateOperand1(locals) - expr->EvaluateOperand2(locals);
149 }
150
151 Value Expression::OpMultiply(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint)
152 {
153         return expr->EvaluateOperand1(locals) * expr->EvaluateOperand2(locals);
154 }
155
156 Value Expression::OpDivide(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint)
157 {
158         return expr->EvaluateOperand1(locals) / expr->EvaluateOperand2(locals);
159 }
160
161 Value Expression::OpBinaryAnd(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint)
162 {
163         return expr->EvaluateOperand1(locals) & expr->EvaluateOperand2(locals);
164 }
165
166 Value Expression::OpBinaryOr(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint)
167 {
168         return expr->EvaluateOperand1(locals) | expr->EvaluateOperand2(locals);
169 }
170
171 Value Expression::OpShiftLeft(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint)
172 {
173         return expr->EvaluateOperand1(locals) << expr->EvaluateOperand2(locals);
174 }
175
176 Value Expression::OpShiftRight(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint)
177 {
178         return expr->EvaluateOperand1(locals) >> expr->EvaluateOperand2(locals);
179 }
180
181 Value Expression::OpEqual(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint)
182 {
183         return expr->EvaluateOperand1(locals) == expr->EvaluateOperand2(locals);
184 }
185
186 Value Expression::OpNotEqual(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint)
187 {
188         return expr->EvaluateOperand1(locals) != expr->EvaluateOperand2(locals);
189 }
190
191 Value Expression::OpLessThan(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint)
192 {
193         return expr->EvaluateOperand1(locals) < expr->EvaluateOperand2(locals);
194 }
195
196 Value Expression::OpGreaterThan(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint)
197 {
198         return expr->EvaluateOperand1(locals) > expr->EvaluateOperand2(locals);
199 }
200
201 Value Expression::OpLessThanOrEqual(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint)
202 {
203         return expr->EvaluateOperand1(locals) <= expr->EvaluateOperand2(locals);
204 }
205
206 Value Expression::OpGreaterThanOrEqual(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint)
207 {
208         return expr->EvaluateOperand1(locals) >= expr->EvaluateOperand2(locals);
209 }
210
211 Value Expression::OpIn(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint)
212 {
213         Value right = expr->EvaluateOperand2(locals);
214
215         if (right.IsEmpty())
216                 return false;
217         else if (!right.IsObjectType<Array>())
218                 BOOST_THROW_EXCEPTION(ConfigError("Invalid right side argument for 'in' operator: " + JsonEncode(right)));
219
220         Value left = expr->EvaluateOperand1(locals);
221                 
222         Array::Ptr arr = right;
223         bool found = false;
224         ObjectLock olock(arr);
225         BOOST_FOREACH(const Value& value, arr) {
226                 if (value == left) {
227                         found = true;
228                         break;
229                 }
230         }
231
232         return found;
233 }
234
235 Value Expression::OpNotIn(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint)
236 {
237         return !OpIn(expr, locals, dhint);
238 }
239
240 Value Expression::OpLogicalAnd(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint)
241 {
242         return expr->EvaluateOperand1(locals).ToBool() && expr->EvaluateOperand2(locals).ToBool();
243 }
244
245 Value Expression::OpLogicalOr(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint)
246 {
247         return expr->EvaluateOperand1(locals).ToBool() || expr->EvaluateOperand2(locals).ToBool();
248 }
249
250 Value Expression::OpFunctionCall(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint)
251 {
252         Value funcName = expr->EvaluateOperand1(locals);
253
254         ScriptFunction::Ptr func;
255
256         if (funcName.IsObjectType<ScriptFunction>())
257                 func = funcName;
258         else
259                 func = ScriptFunction::GetByName(funcName);
260
261         if (!func)
262                 BOOST_THROW_EXCEPTION(ConfigError("Function '" + funcName + "' does not exist."));
263
264         Array::Ptr arr = expr->EvaluateOperand2(locals);
265         std::vector<Value> arguments;
266         for (Array::SizeType index = 0; index < arr->GetLength(); index++) {
267                 const Expression::Ptr& aexpr = arr->Get(index);
268                 arguments.push_back(aexpr->Evaluate(locals));
269         }
270
271         return func->Invoke(arguments);
272 }
273
274 Value Expression::OpArray(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint)
275 {
276         Array::Ptr arr = expr->m_Operand1;
277         Array::Ptr result = make_shared<Array>();
278
279         if (arr) {
280                 for (Array::SizeType index = 0; index < arr->GetLength(); index++) {
281                         const Expression::Ptr& aexpr = arr->Get(index);
282                         result->Add(aexpr->Evaluate(locals));
283                 }
284         }
285
286         return result;
287 }
288
289 Value Expression::OpDict(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint)
290 {
291         Array::Ptr arr = expr->m_Operand1;
292         bool in_place = expr->m_Operand2;
293         Dictionary::Ptr result = make_shared<Dictionary>();
294
295         result->Set("__parent", locals);
296
297         if (arr) {
298                 for (Array::SizeType index = 0; index < arr->GetLength(); index++) {
299                         const Expression::Ptr& aexpr = arr->Get(index);
300                         Dictionary::Ptr alocals = in_place ? locals : result;
301                         aexpr->Evaluate(alocals, dhint);
302
303                         if (alocals->Contains("__result"))
304                                 break;
305                 }
306         }
307
308         Dictionary::Ptr xresult = result->ShallowClone();
309         xresult->Remove("__parent");
310         return xresult;
311 }
312
313 Value Expression::OpSet(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint)
314 {
315         Array::Ptr left = expr->m_Operand1;
316         Array::Ptr indexer = left->Get(0);
317         int csop = left->Get(1);
318
319         DebugHint *sdhint = dhint;
320
321         Value parent, object;
322         String index;
323
324         for (Array::SizeType i = 0; i < indexer->GetLength(); i++) {
325                 Expression::Ptr indexExpr = indexer->Get(i);
326                 String tempindex = indexExpr->Evaluate(locals, dhint);
327
328                 if (i == indexer->GetLength() - 1)
329                         index = tempindex;
330
331                 if (i == 0) {
332                         parent = locals;
333                         object = locals->Get(tempindex);
334                 } else {
335                         parent = object;
336
337                         Expression::Ptr eparent = make_shared<Expression>(&Expression::OpLiteral, parent, expr->m_DebugInfo);
338                         Expression::Ptr eindex = make_shared<Expression>(&Expression::OpLiteral, tempindex, expr->m_DebugInfo);
339
340                         Expression::Ptr eip = make_shared<Expression>(&Expression::OpIndexer, eparent, eindex, expr->m_DebugInfo);
341                         object = eip->Evaluate(locals, dhint);
342                 }
343
344                 if (sdhint)
345                         sdhint = sdhint->GetChild(index);
346
347                 if (i != indexer->GetLength() - 1 && object.IsEmpty()) {
348                         object = make_shared<Dictionary>();
349
350                         Dictionary::Ptr pdict = parent;
351                         pdict->Set(tempindex, object);
352                 }
353         }
354
355         Value right = expr->EvaluateOperand2(locals, dhint);
356
357         if (csop != OpSetLiteral) {
358                 Expression::OpCallback op;
359
360                 switch (csop) {
361                         case OpSetAdd:
362                                 op = &Expression::OpAdd;
363                                 break;
364                         case OpSetSubtract:
365                                 op = &Expression::OpSubtract;
366                                 break;
367                         case OpSetMultiply:
368                                 op = &Expression::OpMultiply;
369                                 break;
370                         case OpSetDivide:
371                                 op = &Expression::OpDivide;
372                                 break;
373                         default:
374                                 VERIFY(!"Invalid opcode.");
375                 }
376
377                 Expression::Ptr ecp = make_shared<Expression>(op,
378                     make_shared<Expression>(&Expression::OpLiteral, object, expr->m_DebugInfo),
379                     make_shared<Expression>(&Expression::OpLiteral, right, expr->m_DebugInfo),
380                     expr->m_DebugInfo);
381
382                 right = ecp->Evaluate(locals, dhint);
383         }
384
385         Dictionary::Ptr pdict = parent;
386         pdict->Set(index, right);
387
388         if (sdhint)
389                 sdhint->AddMessage("=", expr->m_DebugInfo);
390
391         return right;
392 }
393
394 Value Expression::OpIndexer(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint)
395 {
396         Value value = expr->EvaluateOperand1(locals);
397         Value index = expr->EvaluateOperand2(locals);
398
399         if (value.IsObjectType<Dictionary>()) {
400                 Dictionary::Ptr dict = value;
401                 return dict->Get(index);
402         } else if (value.IsObjectType<Array>()) {
403                 Array::Ptr arr = value;
404                 return arr->Get(index);
405         } else if (value.IsObjectType<Object>()) {
406                 Object::Ptr object = value;
407                 Type::Ptr type = object->GetReflectionType();
408
409                 if (!type)
410                         BOOST_THROW_EXCEPTION(ConfigError("Dot operator applied to object which does not support reflection"));
411
412                 int field = type->GetFieldId(index);
413
414                 if (field == -1)
415                         BOOST_THROW_EXCEPTION(ConfigError("Tried to access invalid property '" + index + "'"));
416
417                 return object->GetField(field);
418         } else if (value.IsEmpty()) {
419                 return Empty;
420         } else {
421                 BOOST_THROW_EXCEPTION(ConfigError("Dot operator cannot be applied to type '" + value.GetTypeName() + "'"));
422         }
423 }
424
425 Value Expression::OpImport(const Expression *expr, const Dictionary::Ptr& locals, DebugHint *dhint)
426 {
427         Value type = expr->EvaluateOperand1(locals);
428         Value name = expr->EvaluateOperand2(locals);
429
430         ConfigItem::Ptr item = ConfigItem::GetObject(type, name);
431
432         if (!item)
433                 BOOST_THROW_EXCEPTION(ConfigError("Import references unknown template: '" + name + "'"));
434
435         item->GetExpressionList()->Evaluate(locals, dhint);
436
437         return Empty;
438 }
439
440 Value Expression::FunctionWrapper(const std::vector<Value>& arguments, const Array::Ptr& funcargs, const Expression::Ptr& expr, const Dictionary::Ptr& scope)
441 {
442         if (arguments.size() < funcargs->GetLength())
443                 BOOST_THROW_EXCEPTION(ConfigError("Too few arguments for function"));
444
445         Dictionary::Ptr locals = make_shared<Dictionary>();
446         locals->Set("__parent", scope);
447
448         for (std::vector<Value>::size_type i = 0; i < std::min(arguments.size(), funcargs->GetLength()); i++)
449                 locals->Set(funcargs->Get(i), arguments[i]);
450
451         expr->Evaluate(locals);
452         return locals->Get("__result");
453 }
454
455 Value Expression::OpFunction(const Expression* expr, const Dictionary::Ptr& locals, DebugHint *dhint)
456 {
457         Array::Ptr left = expr->m_Operand1;
458         Expression::Ptr aexpr = left->Get(1);
459         String name = left->Get(0);
460
461         Array::Ptr funcargs = expr->m_Operand2;
462         ScriptFunction::Ptr func = make_shared<ScriptFunction>(boost::bind(&Expression::FunctionWrapper, _1, funcargs, aexpr, locals));
463
464         if (!name.IsEmpty())
465                 ScriptFunction::Register(name, func);
466
467         return func;
468 }
469
470 Value Expression::OpApply(const Expression* expr, const Dictionary::Ptr& locals, DebugHint *dhint)
471 {
472         Array::Ptr left = expr->m_Operand1;
473         Expression::Ptr exprl = expr->m_Operand2;
474         String type = left->Get(0);
475         String target = left->Get(1);
476         Expression::Ptr aname = left->Get(2);
477         Expression::Ptr filter = left->Get(3);
478         String fkvar = left->Get(4);
479         String fvvar = left->Get(5);
480         Expression::Ptr fterm = left->Get(6);
481
482         String name = aname->Evaluate(locals, dhint);
483
484         ApplyRule::AddRule(type, target, name, exprl, filter, fkvar, fvvar, fterm, expr->m_DebugInfo, locals);
485
486         return Empty;
487 }
488
489 Value Expression::OpObject(const Expression* expr, const Dictionary::Ptr& locals, DebugHint *dhint)
490 {
491         Array::Ptr left = expr->m_Operand1;
492         Expression::Ptr exprl = expr->m_Operand2;
493         bool abstract = left->Get(0);
494         String type = left->Get(1);
495         Expression::Ptr aname = left->Get(2);
496         Expression::Ptr filter = left->Get(3);
497         String zone = left->Get(4);
498
499         String name = aname->Evaluate(locals, dhint);
500
501         ConfigItemBuilder::Ptr item = make_shared<ConfigItemBuilder>(expr->m_DebugInfo);
502
503         String checkName = name;
504
505         if (!abstract) {
506                 shared_ptr<NameComposer> nc = dynamic_pointer_cast<NameComposer>(Type::GetByName(type));
507
508                 if (nc)
509                         checkName = nc->MakeName(name, Dictionary::Ptr());
510         }
511
512         if (!checkName.IsEmpty()) {
513                 ConfigItem::Ptr oldItem = ConfigItem::GetObject(type, checkName);
514
515                 if (oldItem) {
516                         std::ostringstream msgbuf;
517                         msgbuf << "Object '" << name << "' of type '" << type << "' re-defined: " << expr->m_DebugInfo << "; previous definition: " << oldItem->GetDebugInfo();
518                         BOOST_THROW_EXCEPTION(ConfigError(msgbuf.str()) << errinfo_debuginfo(expr->m_DebugInfo));
519                 }
520         }
521
522         item->SetType(type);
523
524         if (name.FindFirstOf("!") != String::NPos) {
525                 std::ostringstream msgbuf;
526                 msgbuf << "Name for object '" << name << "' of type '" << type << "' is invalid: Object names may not contain '!'";
527                 BOOST_THROW_EXCEPTION(ConfigError(msgbuf.str()) << errinfo_debuginfo(expr->m_DebugInfo));
528         }
529
530         item->SetName(name);
531
532         item->AddExpression(exprl);
533         item->SetAbstract(abstract);
534         item->SetScope(locals);
535         item->SetZone(zone);
536         item->Compile()->Register();
537
538         ObjectRule::AddRule(type, name, exprl, filter, expr->m_DebugInfo, locals);
539
540         return Empty;
541 }
542
543 Value Expression::OpFor(const Expression* expr, const Dictionary::Ptr& locals, DebugHint *dhint)
544 {
545         Array::Ptr left = expr->m_Operand1;
546         String kvar = left->Get(0);
547         String vvar = left->Get(1);
548         Expression::Ptr aexpr = left->Get(2);
549         Expression::Ptr ascope = expr->m_Operand2;
550
551         Value value = aexpr->Evaluate(locals, dhint);
552
553         if (value.IsObjectType<Array>()) {
554                 if (!vvar.IsEmpty())
555                         BOOST_THROW_EXCEPTION(ConfigError("Cannot use dictionary iterator for array.") << errinfo_debuginfo(expr->m_DebugInfo));
556
557                 Array::Ptr arr = value;
558
559                 ObjectLock olock(arr);
560                 BOOST_FOREACH(const Value& value, arr) {
561                         Dictionary::Ptr xlocals = make_shared<Dictionary>();
562                         xlocals->Set("__parent", locals);
563                         xlocals->Set(kvar, value);
564
565                         ascope->Evaluate(xlocals, dhint);
566                 }
567         } else if (value.IsObjectType<Dictionary>()) {
568                 if (vvar.IsEmpty())
569                         BOOST_THROW_EXCEPTION(ConfigError("Cannot use array iterator for dictionary.") << errinfo_debuginfo(expr->m_DebugInfo));
570
571                 Dictionary::Ptr dict = value;
572
573                 ObjectLock olock(dict);
574                 BOOST_FOREACH(const Dictionary::Pair& kv, dict) {
575                         Dictionary::Ptr xlocals = make_shared<Dictionary>();
576                         xlocals->Set("__parent", locals);
577                         xlocals->Set(kvar, kv.first);
578                         xlocals->Set(vvar, kv.second);
579
580                         ascope->Evaluate(xlocals, dhint);
581                 }
582         } else
583                 BOOST_THROW_EXCEPTION(ConfigError("Invalid type in __for expression: " + value.GetTypeName()) << errinfo_debuginfo(expr->m_DebugInfo));
584
585         return Empty;
586 }
587
588 Dictionary::Ptr DebugHint::ToDictionary(void) const
589 {
590         Dictionary::Ptr result = make_shared<Dictionary>();
591
592         Array::Ptr messages = make_shared<Array>();
593         typedef std::pair<String, DebugInfo> MessageType;
594         BOOST_FOREACH(const MessageType& message, Messages) {
595                 Array::Ptr amsg = make_shared<Array>();
596                 amsg->Add(message.first);
597                 amsg->Add(message.second.Path);
598                 amsg->Add(message.second.FirstLine);
599                 amsg->Add(message.second.FirstColumn);
600                 amsg->Add(message.second.LastLine);
601                 amsg->Add(message.second.LastColumn);
602                 messages->Add(amsg);
603         }
604
605         result->Set("messages", messages);
606
607         Dictionary::Ptr properties = make_shared<Dictionary>();
608
609         typedef std::map<String, DebugHint>::value_type ChildType;
610         BOOST_FOREACH(const ChildType& kv, Children) {
611                 properties->Set(kv.first, kv.second.ToDictionary());
612         }
613
614         result->Set("properties", properties);
615
616         return result;
617 }
618
619 Expression::Ptr icinga::MakeLiteral(const Value& lit)
620 {
621         return make_shared<Expression>(&Expression::OpLiteral, lit, DebugInfo());
622 }