1 //******************************************************************
3 // Copyright 2014 Intel Corporation All Rights Reserved.
4 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
11 #include "OCReflect.h"
12 #include "OCException.h"
13 #include "OCProperties.h"
15 namespace OC { namespace OCReflect {
19 template <class BoundF>
24 const property_type return_type;
25 const property_type_vector param_types;
27 call_through(BoundF& f_, const property_type& return_type_, const property_type_vector param_types_)
28 : f(f_), return_type(return_type_), param_types(param_types_)
33 return make_property(f(), "return value"); // JFW: need a version of this for anonymous properties
36 template <class ...XS>
37 property operator()(const XS& ...params)
40 //return make_property(f(), "foo");
44 // return make_property(f(params...), "fancy result name");
46 return make_property("Hello, World!", "fancy result name");
51 template <typename InstanceT, typename MethodT>
52 OC::OCReflect::bound_function bind_function(InstanceT *self, MethodT const& method)
54 return [self, method](const property_vector& args) -> property
56 auto b = std::bind(method, self);
57 return OC::OCReflect::make_property::apply(b(args), "_ret_");
61 template <typename InstanceT, typename MethodT, typename ...ParameterT>
62 void bind_service(OC::OCServer& server, InstanceT *self, MethodT const& method, const std::string& binding_name, const property_type& return_type, const ParameterT& ...param_types)
64 OC::OCReflect::bound_function f {
65 [method, self](const property_vector& args) -> property
67 // JFW: auto b = std::bind(method, self);
69 /* JFW: eventually, map parameters in to e return OC::OCReflect::make_property::apply(b(args), "_ret_");
70 ...this is tricky, so we' punting on it for the Tuesday release. */
72 return OC::OCReflect::make_property::apply("hello from your friendly neighborhood lambda", "return value");
76 OC::OCReflect::method_binding fmb(binding_name, f,
77 return_type, property_type_vector { param_types... });
82 call_through<decltype(b)> ct(b, return_type, ptypes);
84 // then, at the call site...
85 auto r = ct(1); // call the function
87 std::function<property_type(ParameterT...)> f = ct;
91 template <typename PropertyT>
92 void bind_property(OC::OCServer& server, PropertyT& property, const std::string& binding_name, const property_type& pt, const property_attribute& pas)
96 }} // namespace OC::OCReflect
105 std::string manufacturer;
112 manufacturer("Integrated Electronics")
116 void update_things() { std::cout << "light::update_things()\n"; }
118 void set_powered(const bool new_state) { m_powered = new_state; }
119 bool get_powered() const { return m_powered; }
121 void set_level(const int new_level, int color) { m_level = new_level; m_color = color; }
122 int get_level() const { return m_level; }
124 /* An example of server-side service binding. Note that this does not need to be a
125 member function: for classes you do not have access to, you can accomplish this with
128 void bindTo(OC::OCServer& server, const std::string& base_URI)
130 using OC::OCReflect::method_signature;
131 using OC::OCReflect::method_binding;
132 using OC::OCReflect::property_signature;
133 using OC::OCReflect::property_binding;
134 using OC::OCReflect::bind_service;
135 using OC::OCReflect::bind_property;
137 using OC::OCReflect::property_type;
139 server.registerResource(this, base_URI);
141 // Bind a nullary method:
142 bind_service( server,
144 &light::update_things,
149 // Bind an unary method:
150 bind_service( server,
151 this, &light::set_powered,
154 property_type::boolean);
156 // Example to map setLevel method using the canonical way in one step:
158 server, // server to bind with
159 this, // instance to bind
160 &light::set_level, // method to bind
161 "setLevel", // service name
162 property_type::nil, // input type
163 property_type::integer, // parameter list starts (level)
164 property_type::integer); // parameter list (color)
167 bind_service(server, this, &light::get_level, "getLevel",
168 property_type::integer);
170 bind_service(server, this, &light::get_powered, "isPowered",
171 property_type::boolean);
173 bind_service(server, this, &light::set_powered, "setPowered",
175 property_type::boolean);
177 // Map powered() as a service:
178 method_signature m_setPowered(
179 property_type::nil, // return type
180 property_type::boolean // parameter list (here, just arity 1)
183 // JFW: below is to say a wrapper for: std::bind(&light::set_powered, this); we'll need
184 // to pretty these up:
185 OC::OCReflect::bound_function f =
186 [](const OC::OCReflect::property_vector& args) -> OC::OCReflect::property
187 { return OC::OCReflect::make_property::apply(nullptr, "ret"); };
189 method_binding b_setPowered(
190 "setPowered", // name to bind with service URL
191 f, // function to bind to the service
192 m_setPowered); // method signature (metadata)
194 server.bind(b_setPowered); // request binding
196 // Example to bind a read-only property in individual steps:
197 property_signature p_manufacturer_signature(property_type::string, OC::OCReflect::property_attribute::r); // read-only
199 OC::OCReflect::named_property_binding p_manufacturer("manufacturer", p_manufacturer_signature);
201 property_binding b_manufacturer(
205 server.bind(b_manufacturer);
207 // The canonical way to bind a property to a server in one step:
209 server, // server to bind to
210 this->manufacturer, // pointer to property
211 "manufacturer", // property binding name
212 OC::OCReflect::property_type::string, // property
213 OC::OCReflect::property_attribute::r // type decoration
219 void show_bindings(const OC::OCServer& server)
223 const auto& methods = server.methods();
225 cout << "Bound methods:\n";
226 for(const auto& m : methods)
228 cout << m.first << ':' << m.second << '\n';
239 l.bindTo(server, "/foo/");
241 catch(OC::OCReflect::reflection_exception& e)
243 std::cerr << "Oops: " << e.what() << '\n';
246 show_bindings(server);