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