Merge "New APIs : hasAttribute, numberOfAttributes, erase in OCRepresentation."
[platform/upstream/iotivity.git] / include / OCApi.h
1 //******************************************************************
2 //
3 // Copyright 2014 Intel Mobile Communications GmbH All Rights Reserved.
4 //
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
6 //
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
10 //
11 //      http://www.apache.org/licenses/LICENSE-2.0
12 //
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
18 //
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
20
21 #ifndef __INTEL_OCAPI_H_2014_07_10
22 #define __INTEL_OCAPI_H_2014_07_10
23
24 #include <string>
25 #include <sstream>
26 #include <vector>
27 #include <map>
28 #include <memory>
29 #include <iterator>
30
31 #include <boost/property_tree/ptree.hpp>
32 #include <boost/property_tree/json_parser.hpp>
33 #include <boost/variant.hpp>
34
35 #include "ocstack.h"
36
37 namespace OC
38 {
39     class OCPlatform;
40     class OCResource;
41     class OCResourceRequest;
42     class OCResourceResponse;
43 } // namespace OC
44
45 namespace OC
46 {
47     enum class OCPlatformStatus
48     {
49         PlatformUp,
50         PlatformDown
51     };
52
53     enum class OCAdvertisementStatus
54     {
55         None
56     };
57
58     typedef std::string URI;
59
60     enum class ServiceType
61     {
62         InProc,
63         OutOfProc
64     };
65
66     enum class ModeType
67     {
68         Server,
69         Client,
70         Both
71     };
72
73     enum class QualityOfService : uint8_t
74     {
75         Confirmable     = OC_CONFIRMABLE,
76         NonConfirmable  = OC_NON_CONFIRMABLE
77     };
78
79     /**
80     *  Data structure to provide the configuration.
81     *  ServiceType: indicate InProc or OutOfProc
82     *  ModeType   : indicate whether we want to do server, client or both
83     *  ipAddress  : ip address of server.
84     *               if you speecifiy 0.0.0.0 : it listens on any interface.
85     *  port       : port of server.
86     *             : if you specifiy 0 : next available random port is used.
87     *             : if you specify 5683 : client discovery can work even if they don't specify port.
88     *  QoS        : Quality of Service : CONFIRMABLE or NON CONFIRMABLE.
89     */
90     struct PlatformConfig
91     {
92         ServiceType                serviceType;
93         ModeType                   mode;
94         std::string                ipAddress;
95         uint16_t                   port;
96
97         QualityOfService           QoS;
98
99         public:
100             PlatformConfig(const ServiceType serviceType_,
101             const ModeType mode_,
102             const std::string& ipAddress_,
103             const uint16_t port_,
104             const QualityOfService QoS_)
105                 : serviceType(serviceType_),
106                 mode(mode_),
107                 ipAddress(ipAddress_),
108                 port(port_),
109                 QoS(QoS_)
110         {}
111     };
112
113     enum RequestHandlerFlag
114     {
115         InitFlag = 1 << 0,
116         RequestFlag = 1 << 1,
117         ObserverFlag = 1 << 2
118     };
119
120     enum class ObserveType
121     {
122         Observe,
123         ObserveAll
124     };
125
126     // Helper function to escape character in a string.
127     std::string escapeString(const std::string& value);
128
129     typedef std::map<std::string, std::string> AttributeMap;
130
131     class OCRepresentation
132     {
133         private:
134         std::string m_uri;
135         AttributeMap m_attributeMap;
136         std::vector<std::string> m_resourceTypes;
137         std::vector<std::string> m_resourceInterfaces;
138         int errorCode;
139
140         std::vector<OCRepresentation> m_children;
141
142         public:
143         OCRepresentation() {}
144
145         bool erase(const std::string& str)
146         {
147             return m_attributeMap.erase(str) != 0;
148         }
149
150         std::string getUri(void) const
151         {
152             return m_uri;
153         }
154
155         template <typename T>
156         void setValue(const std::string& str, const T& val);
157
158         template <typename T>
159         bool getValue(const std::string& str, T& val) const;
160
161         template <typename T>
162         T getValue(const std::string& str) const;
163
164         bool hasAttribute(const std::string& str) const
165         {
166             return m_attributeMap.find(str) != m_attributeMap.end();
167         }
168
169         int numberOfAttributes() const
170         {
171             return m_attributeMap.size();
172         }
173
174         void setUri(std::string uri)
175         {
176             m_uri = uri;
177         }
178
179         std::vector<OCRepresentation> getChildren(void) const
180         {
181             return m_children;
182         }
183
184         void setChildren(const std::vector<OCRepresentation>& children)
185         {
186             m_children = children;
187         }
188
189         std::weak_ptr<OCResource> getResource() const
190         {
191             // TODO Needs to be implemented
192             std::weak_ptr<OCResource> wp;
193             return wp;
194         }
195
196         AttributeMap getAttributeMap() const
197         {
198             return m_attributeMap;
199         }
200
201         void setAttributeMap(const AttributeMap& map)
202         {
203             m_attributeMap = map;
204         }
205
206         std::string getJSONRepresentation(void) const
207         {
208             std::ostringstream json;
209
210             json << "{";
211
212             for(auto itr = m_attributeMap.begin(); itr!= m_attributeMap.end(); ++ itr)
213             {
214                 if(itr != m_attributeMap.begin())
215                 {
216                     json << ',';
217                 }
218                 json << "\""<<itr->first<<"\":"<< itr->second;
219             }
220             json << "}";
221
222             return json.str();
223         }
224
225         std::vector<std::string> getResourceTypes() const
226         {
227             return m_resourceTypes;
228         }
229
230         void setResourceTypes(const std::vector<std::string>& resourceTypes)
231         {
232             m_resourceTypes = resourceTypes;
233         }
234
235         std::vector<std::string> getResourceInterfaces(void) const
236         {
237             return m_resourceInterfaces;
238         }
239
240         void setResourceInterfaces(const std::vector<std::string>& resourceInterfaces)
241         {
242             m_resourceInterfaces = resourceInterfaces;
243         }
244     };
245
246     typedef boost::variant<
247                 // TODO NULL value to be implmented.
248                 int,
249                 double,
250                 bool,
251                 std::string,
252                 std::vector<int>,
253                 std::vector<double>,
254                 std::vector<bool>,
255                 std::vector<std::string>,
256                 OCRepresentation> AttributeValue;
257
258     template <typename T>
259     inline std::string getJSONFromVector(std::vector<T> v)
260     {
261         std::ostringstream json;
262
263         json << "\"[";
264         if(v.size() != 0)
265         {
266             std::copy(v.begin(), v.end() - 1, std::ostream_iterator<T>(json, ","));
267             json << v.back();
268         }
269         json << "]\"";
270
271         return json.str();
272     }
273
274     class ComposeVisitor : public boost::static_visitor<std::string>
275     {
276         public:
277
278             // TODO different int sizes
279             std::string operator() (const int i) const
280             {
281                 return std::to_string(i);
282             }
283
284             std::string operator() (const double d) const
285             {
286                 return std::to_string(d);
287             }
288
289             std::string operator() (const std::string& str) const
290             {
291                 std::ostringstream json;
292                 json << "\"";
293                 json << str;
294                 json << "\"";
295
296                 return json.str();
297             }
298
299             std::string operator() (const bool b) const
300             {
301                 if(b)
302                 {
303                     return "true";
304                 }
305                 else
306                 {
307                     return "false";
308                 }
309             }
310
311             std::string operator() (const std::vector<int> numbers) const
312             {
313                 return getJSONFromVector(numbers);
314             }
315
316             std::string operator() (const std::vector<double> numbers) const
317             {
318                 return getJSONFromVector(numbers);
319             }
320
321             std::string operator() (const std::vector<bool> bools) const
322             {
323                 std::ostringstream json;
324                 int first = 1;
325
326                 json << "\"[";
327                 for(auto b: bools)
328                 {
329                     if(first)
330                     {
331                         b ? json << "true" : json << "false";
332                         first = 0;
333                     }
334                     else
335                     {
336                         b ? json << ",true" : json << ",false";
337                     }
338                 }
339                 json << "]\"";
340
341                 return json.str();
342             }
343
344             std::string operator() (const std::vector<std::string> strings) const
345             {
346                 return getJSONFromVector(strings);
347             }
348
349             std::string operator() (const OCRepresentation& rep) const
350             {
351                 std::ostringstream json;
352
353                 json << "\"";
354
355                 json << escapeString(rep.getJSONRepresentation());
356
357                 json << "\"";
358
359                 return json.str();
360             }
361
362     };
363
364     inline void split(std::string input, char delimiter, std::vector<std::string>& tokens)
365     {
366         std::stringstream ss(input);
367         std::string item;
368
369         while(std::getline(ss, item, delimiter))
370         {
371             tokens.push_back(item);
372         }
373     }
374
375     class ParseVisitor : public boost::static_visitor<void>
376     {
377         public:
378
379             ParseVisitor(std::string str): m_str(str)
380             {
381             }
382
383             void operator() (int& i) const
384             {
385                 i = std::stoi(m_str);
386             }
387
388             void operator() (double& d) const
389             {
390                 d = std::stod(m_str);
391             }
392
393             void operator() (std::string& str) const
394             {
395                 str = m_str;
396             }
397
398             void operator() (bool& b) const
399             {
400                 b = m_str.compare("true") == 0;
401             }
402
403             void operator() (std::vector<int>& numbers) const
404             {
405                 numbers.clear();
406
407                 if(m_str.length() >= 2)
408                 {
409                     std::string str = m_str.substr(1, m_str.length()-2);
410
411                     std::vector<std::string> tokens;
412                     split(str, ',', tokens);
413
414                     for(auto s: tokens)
415                     {
416                         numbers.push_back(std::stoi(s));
417                     }
418                 }
419                 else
420                 {
421                     // TODO Logging
422                     std::cout << "Array type should have atleast []\n";
423                 }
424
425             }
426
427             void operator() (std::vector<double>& numbers) const
428             {
429                 numbers.clear();
430
431                 if(m_str.length() >= 2)
432                 {
433                     std::string str = m_str.substr(1, m_str.length()-2);
434                     std::vector<std::string> tokens;
435                     split(str, ',', tokens);
436
437                     for(auto s: tokens)
438                     {
439                         numbers.push_back(std::stod(s));
440                     }
441                 }
442                 else
443                 {
444                     // TODO Logging
445                     std::cout << "Array type should have atleast []\n";
446                 }
447             }
448
449             void operator() (std::vector<bool>& bools) const
450             {
451                 bools.clear();
452
453                 if(m_str.length() >= 2)
454                 {
455                     std::string str = m_str.substr(1, m_str.length()-2);
456
457                     std::vector<std::string> tokens;
458                     split(str, ',', tokens);
459
460                     for(auto s: tokens)
461                     {
462                         bools.push_back(s.compare("true") == 0);
463                     }
464                 }
465                 else
466                 {
467                     // TODO Logging
468                     std::cout << "Array type should have atleast []\n";
469                 }
470
471             }
472
473             void operator() (std::vector<std::string>& strings) const
474             {
475                 strings.clear();
476
477                 if(m_str.length() >= 2)
478                 {
479                     std::string str = m_str.substr(1, m_str.length()-2);
480
481                     std::vector<std::string> tokens;
482                     split(str, ',', tokens);
483
484                     for(auto s: tokens)
485                     {
486                         strings.push_back(s);
487                     }
488                 }
489                 else
490                 {
491                     // TODO Logging
492                     std::cout << "Array type should have atleast []\n";
493                 }
494             }
495
496             void operator() (OCRepresentation& rep) const
497             {
498                 // TODO this will refactored
499                 AttributeMap attributeMap;
500
501                 std::stringstream requestStream;
502                 requestStream << m_str;
503                 boost::property_tree::ptree payload;
504                 try
505                 {
506                     boost::property_tree::read_json(requestStream, payload);
507                 }
508                 catch(boost::property_tree::json_parser::json_parser_error &e)
509                 {
510                     //TODO: log this
511                     std::cout << "Parse error\n";
512                     return;
513                 }
514
515                 for(auto& item: payload)
516                 {
517                     std::string name = item.first.data();
518                     std::string value = item.second.data();
519
520                     attributeMap[name] = value;
521                 }
522
523                 rep.setAttributeMap(attributeMap);
524             }
525
526         private:
527             std::string m_str;
528     };
529
530
531     inline std::string getJSON(const AttributeValue& v)
532     {
533         return boost::apply_visitor(ComposeVisitor(), v);
534     }
535
536     inline void parseJSON(AttributeValue& v, std::string str)
537     {
538         boost::apply_visitor(ParseVisitor(str), v);
539     }
540
541     template <typename T>
542     void OCRepresentation::setValue(const std::string& str, const T& val)
543     {
544         m_attributeMap[str] = getJSON(val);
545     }
546
547     template <typename T>
548     T OCRepresentation::getValue(const std::string& str) const
549     {
550         T val;
551
552         auto x = m_attributeMap.find(str);
553
554         if(m_attributeMap.end() != x)
555         {
556             AttributeValue v = val;
557             parseJSON(v, x->second);
558             val = boost::get<T>(v);
559         }
560
561         return val;
562     }
563
564     template <typename T>
565     bool OCRepresentation::getValue(const std::string& str, T& val) const
566     {
567         auto x = m_attributeMap.find(str);
568
569         if(m_attributeMap.end() != x)
570         {
571             AttributeValue v = val;
572             parseJSON(v, x->second);
573             val = boost::get<T>(v);
574             return true;
575         }
576         else
577         {
578             return false;
579         }
580     }
581
582
583     // Typedef for query parameter map
584     typedef std::map<std::string, std::string> QueryParamsMap;
585
586     // Typedef for list of observation IDs
587     typedef std::vector<OCObservationId> ObservationIds;
588
589     enum class ObserveAction
590     {
591         ObserveRegister,
592         ObserveUnregister
593     };
594
595     typedef struct
596     {
597         // Action associated with observation request
598         ObserveAction action;
599         // Identifier for observation being registered/unregistered
600         OCObservationId obsId;
601     } ObservationInfo;
602
603     // const strings for different interfaces
604
605     // Default interface
606     const std::string DEFAULT_INTERFACE = "oc.mi.def";
607
608     // Used in discovering (GET) links to other resources of a collection.
609     const std::string LINK_INTERFACE = "oc.mi.ll";
610
611     // Used in GET, PUT, POST, DELETE methods on links to other resources of a collection.
612     const std::string BATCH_INTERFACE = "oc.mi.b";
613
614     typedef std::function<void(std::shared_ptr<OCResource>)> FindCallback;
615     typedef std::function<void(const std::shared_ptr<OCResourceRequest>, const std::shared_ptr<OCResourceResponse>)> RegisterCallback;
616     typedef std::function<void(OCStackResult, const unsigned int)> SubscribeCallback;
617     typedef std::function<void(const OCRepresentation&, const int)> GetCallback;
618     typedef std::function<void(const OCRepresentation&, const int)> PutCallback;
619     typedef std::function<void(const OCRepresentation&, const int, const int)> ObserveCallback;
620 } // namespace OC
621
622 #endif