Add support for vtable flags for properties

This adds support for specifying the vtable flags
`SD_BUS_VTABLE_DEPRECATED`, `SD_BUS_VTABLE_HIDDEN`,
`SD_BUS_VTABLE_UNPRIVILEGED`, `SD_BUS_VTABLE_PROPERTY_CONST`,
`SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE`,
`SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION` and
`SD_BUS_VTABLE_PROPERTY_EXPLICIT` for properties. The list of flags in
the YAML files will be ORed together. If no flags have been specified,
we add SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE by default (as before, just
too preserve the behavior; even though one would maybe like to specify
this explicitly).

Change-Id: Ib752cae6e74b2265c75e68707e2520f88f3181e8
Signed-off-by: Waqar Hameed <waqarh@axis.com>
diff --git a/docs/interface.md b/docs/interface.md
index ff63c34..08db52a 100644
--- a/docs/interface.md
+++ b/docs/interface.md
@@ -150,13 +150,21 @@
 
 ## Properties
 
-A property must have the YAML property `name` and `type` and may optionally
-have `description`, `flags`, `default`, and `errors`.  The `default` defines the
+A property must have the YAML property `name` and `type` and may optionally have
+`description`, `flags`, `default`, and `errors`. The `default` defines the
 default value of the property. See the `Methods` section above for more
 information on errors.
-The only current supported value for `flags` is `const`, which corresponds to
-SD_BUS_VTABLE_PROPERTY_CONST, making the property read-only via D-Bus but
-still writable by the app implementing it.
+
+The supported values for `flags` are `deprecated`, `hidden`, `unprivileged`,
+`const`, `emits_change`, `emits_invalidation`, `explicit` , which corresponds to
+`SD_BUS_VTABLE_DEPRECATED`, `SD_BUS_VTABLE_HIDDEN`,
+`SD_BUS_VTABLE_UNPRIVILEGED`, `SD_BUS_VTABLE_PROPERTY_CONST`,
+`SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE`,
+`SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION` and
+`SD_BUS_VTABLE_PROPERTY_EXPLICIT`, respectively.  The flag `const ` makes the
+property read-only via D-Bus but still writable by the app implementing
+it. Moreover, if no flags have been specified for a property, `emits_change`
+will be added by default.
 
 Example:
 ```
diff --git a/tools/sdbusplus/property.py b/tools/sdbusplus/property.py
index b7808d3..afea22b 100644
--- a/tools/sdbusplus/property.py
+++ b/tools/sdbusplus/property.py
@@ -14,6 +14,7 @@
         self.cppTypeName = self.parse_cpp_type(self.typeName)
         self.defaultValue = kwargs.pop('default', None)
         self.flags = kwargs.pop('flags', [])
+        self.cpp_flags = self.or_cpp_flags(self.flags)
         self.errors = kwargs.pop('errors', [])
 
         if (self.defaultValue is not None):
@@ -189,3 +190,23 @@
     def cpp_prototype(self, loader, interface, ptype):
         return self.render(loader, "property.prototype.hpp.mako", property=self,
                            interface=interface, ptype=ptype, post=str.rstrip)
+
+    def or_cpp_flags(self, flags):
+        """Return the corresponding ORed cpp flags."""
+        flags_dict = {
+            "deprecated": "vtable::common_::deprecated",
+            "hidden": "vtable::common_::hidden",
+            "unprivileged": "vtable::common_::unprivileged",
+            "const": "vtable::property_::const_",
+            "emits_change": "vtable::property_::emits_change",
+            "emits_invalidation": "vtable::property_::emits_invalidation",
+            "explicit": "vtable::property_::explicit_"}
+
+        cpp_flags = []
+        for flag in flags:
+            try:
+                cpp_flags.append(flags_dict[flag])
+            except KeyError:
+                raise ValueError("Invalid flag \"{}\"".format(flag))
+
+        return " | ".join(cpp_flags)
diff --git a/tools/sdbusplus/templates/interface.server.cpp.mako b/tools/sdbusplus/templates/interface.server.cpp.mako
index 062cbf7..9acfa2f 100644
--- a/tools/sdbusplus/templates/interface.server.cpp.mako
+++ b/tools/sdbusplus/templates/interface.server.cpp.mako
@@ -148,12 +148,14 @@
                      details::${classname}::_property_${p.name}
                         .data(),
                      _callback_get_${p.name},
-        % if 'const' in p.flags:
-                     vtable::property_::const_),
-        % else:
+        % if 'const' not in p.flags:
                      _callback_set_${p.name},
+        % endif
+        % if not p.cpp_flags:
                      vtable::property_::emits_change),
-        %endif
+        % else:
+                     ${p.cpp_flags}),
+        % endif
     % endfor
     vtable::end()
 };