Fix RE unit test case. (#632)
[platform/upstream/iotivity.git] / service / resource-encapsulation / src / resourceClient / RCSRemoteResourceObject.cpp
1 //******************************************************************
2 //
3 // Copyright 2015 Samsung Electronics 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 #include "RCSRemoteResourceObject.h"
22
23 #include "OCPlatform.h"
24
25 #include "ResourceBroker.h"
26 #include "ResourceCacheManager.h"
27
28 #include "ScopeLogger.h"
29
30 #define TAG PCF("RCSRemoteResourceObject")
31
32 namespace
33 {
34     using namespace OIC::Service;
35
36     ResourceState convertBrokerState(BROKER_STATE state)
37     {
38         SCOPE_LOG_F(DEBUG, TAG);
39
40         switch (state)
41         {
42             case BROKER_STATE::ALIVE:
43                 return ResourceState::ALIVE;
44
45             case BROKER_STATE::REQUESTED:
46                 return ResourceState::REQUESTED;
47
48             case BROKER_STATE::LOST_SIGNAL:
49                 return ResourceState::LOST_SIGNAL;
50
51             case BROKER_STATE::DESTROYED:
52                 return ResourceState::DESTROYED;
53
54             case BROKER_STATE::NONE:
55                 return ResourceState::NONE;
56         }
57
58         return ResourceState::NONE;
59     }
60
61     CacheState convertCacheState(CACHE_STATE state)
62     {
63         SCOPE_LOG_F(DEBUG, TAG);
64
65         switch (state)
66         {
67             case CACHE_STATE::READY:
68                 return CacheState::READY;
69
70             case CACHE_STATE::READY_YET:
71             case CACHE_STATE::UPDATING:
72                 return CacheState::UNREADY;
73
74             case CACHE_STATE::LOST_SIGNAL:
75                 return CacheState::LOST_SIGNAL;
76
77             case CACHE_STATE::DESTROYED:
78             case CACHE_STATE::NONE:
79                 return CacheState::NONE;
80         }
81
82         return CacheState::NONE;
83     }
84
85     OCStackResult hostingCallback(BROKER_STATE state,
86             RCSRemoteResourceObject::StateChangedCallback onResourceStateChanged)
87     {
88         SCOPE_LOG_F(DEBUG, TAG);
89
90         onResourceStateChanged(convertBrokerState(state));
91         return OC_STACK_OK;
92     }
93
94     OCStackResult cachingCallback(std::shared_ptr< PrimitiveResource >,
95             const RCSResourceAttributes& data, int eCode,
96             RCSRemoteResourceObject::CacheUpdatedCallback onCacheUpdated,
97             std::weak_ptr<RCSRemoteResourceObject> resourcePtr)
98     {
99         SCOPE_LOG_F(DEBUG, TAG);
100
101         std::shared_ptr<RCSRemoteResourceObject> resource = resourcePtr.lock();
102         if(!resource)
103         {
104             OIC_LOG(ERROR, TAG, "Resource object is null");
105             return OC_STACK_OK;
106         }
107
108         //If error code is failure then RE Cache module should
109         //do clean up for caching flags, maps etc.
110         if(eCode > 4)
111         {
112             OIC_LOG_V(ERROR, TAG, "Error code: %d", eCode);
113             try
114             {
115                 resource->stopCaching();
116             }
117             catch(...)
118             {
119                 //Exception will be thrown: stack will return OC_STACK_ERROR
120                 //if it already stopped observe. This call is reqired for clearing
121                 //Cache manager.
122                 OIC_LOG(DEBUG, TAG, "Cleared Cache");
123             }
124         }
125
126         //Calling application callback
127         onCacheUpdated(data, eCode);
128         return OC_STACK_OK;
129     }
130
131     void setRemoteAttributesCb(const HeaderOptions&, const ResponseStatement& response, int eCode,
132             RCSRemoteResourceObject::RemoteAttributesSetCallback onRemoteAttributesSet)
133     {
134         SCOPE_LOG_F(DEBUG, TAG);
135
136         onRemoteAttributesSet(response.getAttributes(), eCode);
137     }
138
139     void getRemoteAttributesCb(const HeaderOptions&, const ResponseStatement& response, int eCode,
140             RCSRemoteResourceObject::RemoteAttributesGetCallback onRemoteAttributesReceived)
141     {
142         SCOPE_LOG_F(DEBUG, TAG);
143
144         onRemoteAttributesReceived(response.getAttributes(), eCode);
145     }
146 }
147
148 namespace OIC
149 {
150     namespace Service
151     {
152
153         RCSQueryParams& RCSQueryParams::setResourceInterface(std::string resourceInterface)
154         {
155             m_resourceInterface = std::move(resourceInterface);
156             return *this;
157         }
158
159         RCSQueryParams& RCSQueryParams::setResourceType(std::string resourceType)
160         {
161             m_resourceType = std::move(resourceType);
162             return *this;
163         }
164
165         RCSQueryParams& RCSQueryParams::put(std::string key, std::string value)
166         {
167             m_map[std::move(key)] = std::move(value);
168             return *this;
169         }
170
171         std::string RCSQueryParams::getResourceInterface() const
172         {
173             return m_resourceInterface;
174         }
175
176         std::string RCSQueryParams::getResourceType() const
177         {
178             return m_resourceType;
179         }
180
181         std::string RCSQueryParams::get(const std::string& key) const
182         {
183             try
184             {
185                 return m_map.at(key);
186             }
187             catch (const std::out_of_range&)
188             {
189                 throw RCSInvalidKeyException(key + " is an invalid key");
190             }
191         }
192
193         const RCSQueryParams::Map& RCSQueryParams::getAll() const
194         {
195             return m_map;
196         }
197
198         RCSRemoteResourceObject::RCSRemoteResourceObject(
199                 std::shared_ptr< PrimitiveResource > primtiveResource) :
200                 m_primitiveResource{ primtiveResource },
201                 m_cacheId{ },
202                 m_brokerId{ }
203         {
204         }
205
206         RCSRemoteResourceObject::~RCSRemoteResourceObject()
207         {
208             SCOPE_LOG_F(DEBUG, TAG);
209
210             try{
211                 stopCaching();
212                 stopMonitoring();
213             }
214             catch(std::exception &e){
215                 OIC_LOG_V(ERROR, TAG, "%s", e.what());
216             }
217         }
218
219         std::weak_ptr< RCSRemoteResourceObject > RCSRemoteResourceObject::weakFromThis()
220         {
221             return shared_from_this();
222         }
223
224         RCSRemoteResourceObject::Ptr RCSRemoteResourceObject::fromOCResource(
225                 std::shared_ptr< OC::OCResource > ocResource)
226         {
227             if (!ocResource)
228             {
229                 throw RCSInvalidParameterException("the oc resource must not be nullptr.");
230             }
231
232             return std::make_shared< RCSRemoteResourceObject >(
233                     PrimitiveResource::create(ocResource));
234         }
235
236         std::shared_ptr< OC::OCResource > RCSRemoteResourceObject::toOCResource(
237         RCSRemoteResourceObject::Ptr rcsResource)
238         {
239             if (!rcsResource)
240             {
241                 throw RCSInvalidParameterException("the rcs resource must not be nullptr.");
242             }
243
244             OC::OCResource::Ptr ocResource = OC::OCPlatform::constructResourceObject(rcsResource->getAddress(),
245                 rcsResource->getUri(),
246                 rcsResource->m_primitiveResource->getConnectivityType(),
247                 rcsResource->isObservable(),
248                 rcsResource->getTypes(),
249                 rcsResource->getInterfaces());
250
251             return ocResource;
252         }
253
254         bool RCSRemoteResourceObject::isMonitoring() const
255         {
256             return m_brokerId != 0;
257         }
258
259         bool RCSRemoteResourceObject::isCaching() const
260         {
261             return m_cacheId != 0;
262         }
263
264         bool RCSRemoteResourceObject::isObservable() const
265         {
266             return m_primitiveResource->isObservable();
267         }
268
269         void RCSRemoteResourceObject::startMonitoring(StateChangedCallback cb)
270         {
271             SCOPE_LOG_F(DEBUG, TAG);
272
273             if (!cb)
274             {
275                 throw RCSInvalidParameterException{ "startMonitoring : Callback is NULL" };
276             }
277
278             if (isMonitoring())
279             {
280                 OIC_LOG(DEBUG, TAG, "startMonitoring : already started");
281                 throw RCSBadRequestException{ "Monitoring already started." };
282             }
283
284             m_brokerId = ResourceBroker::getInstance()->hostResource(m_primitiveResource,
285                     std::bind(hostingCallback, std::placeholders::_1, std::move(cb)));
286         }
287
288         void RCSRemoteResourceObject::stopMonitoring()
289         {
290             SCOPE_LOG_F(DEBUG, TAG);
291
292             if (!isMonitoring())
293             {
294                 OIC_LOG(DEBUG, TAG, "stopMonitoring : Not started");
295                 return;
296             }
297
298             ResourceBroker::getInstance()->cancelHostResource(m_brokerId);
299             m_brokerId = 0;
300         }
301
302         ResourceState RCSRemoteResourceObject::getState() const
303         {
304             SCOPE_LOG_F(DEBUG, TAG);
305
306             if (!isMonitoring())
307             {
308                 return ResourceState::NONE;
309             }
310
311             return convertBrokerState(
312                     ResourceBroker::getInstance()->getResourceState(m_primitiveResource));
313         }
314
315         void RCSRemoteResourceObject::startCaching()
316         {
317             startCaching({ });
318         }
319
320         void RCSRemoteResourceObject::startCaching(CacheUpdatedCallback cb,
321             CacheMode mode, CacheReport reportType)
322         {
323             SCOPE_LOG_F(DEBUG, TAG);
324
325             if (isCaching())
326             {
327                 OIC_LOG(DEBUG, TAG, "startCaching : already Started");
328                 throw RCSBadRequestException{ "Caching already started." };
329             }
330
331             REPORT_FREQUENCY freq;
332             if (reportType == CacheReport::REPORT_CHANGES)
333             {
334                 freq = REPORT_FREQUENCY::UPTODATE;
335             }
336             else if(reportType == CacheReport::REPORT_ALL)
337             {
338                 freq = REPORT_FREQUENCY::WHENEVER_NOTIFIED;
339             }
340
341             if (mode == CacheMode::OBSERVE_ONLY)
342             {
343                 m_cacheId = ResourceCacheManager::getInstance()->requestResourceCache(
344                         m_primitiveResource,
345                         std::bind(cachingCallback, std::placeholders::_1,
346                                   std::placeholders::_2, std::placeholders::_3,
347                                   std::move(cb), weakFromThis()), CACHE_METHOD::OBSERVE_ONLY,
348                                   freq, 0);
349             }
350             else if (cb)
351             {
352                 m_cacheId = ResourceCacheManager::getInstance()->requestResourceCache(
353                         m_primitiveResource,
354                         std::bind(cachingCallback, std::placeholders::_1,
355                                 std::placeholders::_2, std::placeholders::_3,
356                                 std::move(cb), weakFromThis()), CACHE_METHOD::ITERATED_GET,
357                                 freq, 0);
358             }
359             else
360             {
361                 m_cacheId = ResourceCacheManager::getInstance()->requestResourceCache(
362                         m_primitiveResource, { }, CACHE_METHOD::ITERATED_GET,
363                         REPORT_FREQUENCY::NONE, 0);
364             }
365
366             OIC_LOG_V(DEBUG, TAG, "startCaching CACHE ID %d", m_cacheId);
367         }
368
369         void RCSRemoteResourceObject::stopCaching()
370         {
371             SCOPE_LOG_F(DEBUG, TAG);
372
373             if (!isCaching())
374             {
375                 OIC_LOG(DEBUG, TAG, "Caching already terminated");
376                 return;
377             }
378
379             try
380             {
381                 ResourceCacheManager::getInstance()->cancelResourceCache(m_cacheId);
382             }
383             catch (const RCSInvalidParameterException &)
384             {
385                 throw;
386             }
387             catch (...)
388             {
389                 m_cacheId = 0;
390                 throw;
391             }
392             m_cacheId = 0;
393         }
394
395         CacheState RCSRemoteResourceObject::getCacheState() const
396         {
397             SCOPE_LOG_F(DEBUG, TAG);
398
399             if (!isCaching())
400             {
401                 return CacheState::NONE;
402             }
403
404             return convertCacheState(
405                     ResourceCacheManager::getInstance()->getResourceCacheState(m_cacheId));
406         }
407
408         bool RCSRemoteResourceObject::isCachedAvailable() const
409         {
410             if (!isCaching())
411             {
412                 return false;
413             }
414
415             return ResourceCacheManager::getInstance()->isCachedData(m_cacheId);
416         }
417
418         RCSResourceAttributes RCSRemoteResourceObject::getCachedAttributes() const
419         {
420             SCOPE_LOG_F(DEBUG, TAG);
421
422             if (!isCaching())
423             {
424                 throw RCSBadRequestException{ "Caching not started." };
425             }
426
427             if (!isCachedAvailable())
428             {
429                 throw RCSBadRequestException{ "Cache data is not available." };
430             }
431
432             return ResourceCacheManager::getInstance()->getCachedData(m_cacheId);
433         }
434
435         RCSResourceAttributes::Value RCSRemoteResourceObject::getCachedAttribute(
436                 const std::string& key) const
437         {
438             SCOPE_LOG_F(DEBUG, TAG);
439
440             return getCachedAttributes().at(key);
441         }
442
443         std::string RCSRemoteResourceObject::getUri() const
444         {
445             return m_primitiveResource->getUri();
446         }
447
448         std::string RCSRemoteResourceObject::getAddress() const
449         {
450             return m_primitiveResource->getHost();
451         }
452
453         std::vector< std::string > RCSRemoteResourceObject::getTypes() const
454         {
455             return m_primitiveResource->getTypes();
456         }
457
458         std::vector< std::string > RCSRemoteResourceObject::getInterfaces() const
459         {
460             return m_primitiveResource->getInterfaces();
461         }
462
463         void RCSRemoteResourceObject::getRemoteAttributes(RemoteAttributesGetCallback cb)
464         {
465             SCOPE_LOG_F(DEBUG, TAG);
466
467             if (!cb)
468             {
469                 throw RCSInvalidParameterException{ "getRemoteAttributes : Callback is empty" };
470             }
471
472             m_primitiveResource->requestGet(
473                     std::bind(getRemoteAttributesCb, std::placeholders::_1, std::placeholders::_2,
474                             std::placeholders::_3, std::move(cb)));
475         }
476
477         void RCSRemoteResourceObject::get(GetCallback cb)
478         {
479             SCOPE_LOG_F(DEBUG, TAG);
480
481             if (!cb)
482             {
483                 throw RCSInvalidParameterException{ "get : Callback is empty" };
484             }
485
486             m_primitiveResource->requestGet(std::move(cb));
487         }
488
489         void RCSRemoteResourceObject::get(const RCSQueryParams& queryParams, GetCallback cb)
490         {
491             SCOPE_LOG_F(DEBUG, TAG);
492
493             if (!cb)
494             {
495                 throw RCSInvalidParameterException{ "get : Callback is empty" };
496             }
497
498             const auto& paramMap = queryParams.getAll();
499
500             m_primitiveResource->requestGetWith(
501                     queryParams.getResourceType(), queryParams.getResourceInterface(),
502                     OC::QueryParamsMap{ paramMap.begin(), paramMap.end() },
503                     std::move(cb));
504         }
505
506         void RCSRemoteResourceObject::setRemoteAttributes(const RCSResourceAttributes& attribute,
507                 RemoteAttributesSetCallback cb)
508         {
509             SCOPE_LOG_F(DEBUG, TAG);
510
511             if (!cb)
512             {
513                 throw RCSInvalidParameterException{ "setRemoteAttributes : Callback is empty" };
514             }
515
516             m_primitiveResource->requestSet(attribute,
517                     std::bind(setRemoteAttributesCb, std::placeholders::_1, std::placeholders::_2,
518                             std::placeholders::_3, cb));
519         }
520
521         void RCSRemoteResourceObject::set(const RCSResourceAttributes& attributes, SetCallback cb)
522         {
523             SCOPE_LOG_F(DEBUG, TAG);
524
525             if (!cb)
526             {
527                 throw RCSInvalidParameterException{ "set : Callback is empty" };
528             }
529
530             m_primitiveResource->requestSet(attributes, std::move(cb));
531         }
532
533         void RCSRemoteResourceObject::set(const RCSQueryParams& queryParams,
534                 const RCSResourceAttributes& attributes, SetCallback cb)
535         {
536             SCOPE_LOG_F(DEBUG, TAG);
537
538             if (!cb)
539             {
540                 throw RCSInvalidParameterException{ "set : Callback is empty" };
541             }
542
543             const auto& paramMap = queryParams.getAll();
544
545             m_primitiveResource->requestSetWith(
546                     queryParams.getResourceType(), queryParams.getResourceInterface(),
547                     OC::QueryParamsMap{ paramMap.begin(), paramMap.end() }, attributes,
548                     std::move(cb));
549         }
550
551         void RCSRemoteResourceObject::set(const RCSQueryParams& queryParams,
552                 const RCSRepresentation& rep, SetCallback cb)
553         {
554             SCOPE_LOG_F(DEBUG, TAG);
555
556             if (!cb)
557             {
558                 throw RCSInvalidParameterException{ "set : Callback is empty" };
559             }
560
561             const auto& paramMap = queryParams.getAll();
562
563             m_primitiveResource->requestSetWith(
564                     queryParams.getResourceType(), queryParams.getResourceInterface(),
565                     OC::QueryParamsMap{ paramMap.begin(), paramMap.end() }, rep,
566                     std::move(cb));
567         }
568
569     }
570 }