Fix for SVACE and Klocwork issues.
[platform/upstream/iotivity.git] / service / simulator / src / server / simulator_single_resource_impl.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 "simulator_single_resource_impl.h"
22 #include "simulator_utils.h"
23 #include "oc_interface_details.h"
24 #include "simulator_logger.h"
25 #include "logger.h"
26
27 #define TAG "SIMULATOR_SINGLE_RESOURCE"
28
29 SimulatorSingleResourceImpl::SimulatorSingleResourceImpl()
30 {
31     m_type = SimulatorResource::Type::SINGLE_RESOURCE;
32     m_interfaces.push_back(OC::DEFAULT_INTERFACE);
33     m_property = static_cast<OCResourceProperty>(OC_DISCOVERABLE | OC_OBSERVABLE);
34     m_resModelSchema = SimulatorResourceModelSchema::build();
35
36     // Set resource supports GET, PUT and POST by default
37     m_requestModels["GET"] = nullptr;
38     m_requestModels["POST"] = nullptr;
39     m_requestModels["PUT"] = nullptr;
40
41     m_resourceHandle = nullptr;
42 }
43
44 void SimulatorSingleResourceImpl::setName(const std::string &name)
45 {
46     VALIDATE_INPUT(name.empty(), "Name is empty!")
47     m_name = name;
48 }
49
50 void SimulatorSingleResourceImpl::setURI(const std::string &uri)
51 {
52     VALIDATE_INPUT(uri.empty(), "Uri is empty!")
53
54     std::lock_guard<std::recursive_mutex> lock(m_objectLock);
55     if (m_resourceHandle)
56     {
57         throw SimulatorException(SIMULATOR_OPERATION_NOT_ALLOWED,
58                                  "URI can not be set when resource is started!");
59     }
60
61     m_uri = uri;
62 }
63
64 void SimulatorSingleResourceImpl::setResourceType(const std::string &resourceType)
65 {
66     VALIDATE_INPUT(resourceType.empty(), "Resource type is empty!")
67
68     std::lock_guard<std::recursive_mutex> lock(m_objectLock);
69     if (m_resourceHandle)
70     {
71         throw SimulatorException(SIMULATOR_OPERATION_NOT_ALLOWED,
72                                  "Resource type cannot be set when resource is started!");
73     }
74
75     m_resourceType = resourceType;
76 }
77
78 void SimulatorSingleResourceImpl::setInterface(const std::string &interfaceType)
79 {
80     VALIDATE_INPUT(interfaceType.empty(), "Interface type list is empty!")
81
82     std::lock_guard<std::recursive_mutex> lock(m_objectLock);
83     if (m_resourceHandle)
84     {
85         throw SimulatorException(SIMULATOR_OPERATION_NOT_ALLOWED,
86                                  "Resource interface can not be reset when resource is started!");
87     }
88
89     m_interfaces = {interfaceType};
90 }
91
92 void SimulatorSingleResourceImpl::setInterface(const std::vector<std::string> &interfaceTypes)
93 {
94     VALIDATE_INPUT(interfaceTypes.empty(), "Interface type list is empty!")
95
96     std::lock_guard<std::recursive_mutex> lock(m_objectLock);
97     if (m_resourceHandle)
98     {
99         throw SimulatorException(SIMULATOR_OPERATION_NOT_ALLOWED,
100                                  "Resource interface can not be reset when resource is started!");
101     }
102
103     m_interfaces.clear();
104     for (auto &interfaceType : interfaceTypes)
105     {
106         if (m_interfaces.end() ==
107             std::find(m_interfaces.begin(), m_interfaces.end(), interfaceType))
108         {
109             m_interfaces.push_back(interfaceType);
110         }
111     }
112 }
113
114 void SimulatorSingleResourceImpl::addInterface(const std::string &interfaceType)
115 {
116     VALIDATE_INPUT(interfaceType.empty(), "Interface type is empty!")
117
118     if (m_interfaces.end() != std::find(m_interfaces.begin(), m_interfaces.end(), interfaceType))
119     {
120         SIM_LOG(ILogger::ERROR, "[" << m_uri << "] "
121                 << "Resource already supporting this Interface: " << interfaceType)
122         return;
123     }
124
125     std::lock_guard<std::recursive_mutex> lock(m_objectLock);
126     if (m_resourceHandle)
127     {
128         typedef OCStackResult (*bindInterfaceToResource)(const OCResourceHandle &,
129                 const std::string &);
130
131         invokeocplatform(static_cast<bindInterfaceToResource>(
132                              OC::OCPlatform::bindInterfaceToResource), m_resourceHandle,
133                          interfaceType);
134     }
135
136     m_interfaces.push_back(interfaceType);
137 }
138
139 void SimulatorSingleResourceImpl::setObservable(bool state)
140 {
141     std::lock_guard<std::recursive_mutex> lock(m_objectLock);
142     if (m_resourceHandle)
143     {
144         throw SimulatorException(SIMULATOR_OPERATION_NOT_ALLOWED,
145                                  "Observation state can not be changed when resource is started!");
146     }
147
148     if (state)
149         m_property = static_cast<OCResourceProperty>(m_property | OC_OBSERVABLE);
150     else
151         m_property = static_cast<OCResourceProperty>(m_property ^ OC_OBSERVABLE);
152 }
153
154 void SimulatorSingleResourceImpl::setDiscoverable(bool state)
155 {
156     std::lock_guard<std::recursive_mutex> lock(m_objectLock);
157     if (m_resourceHandle)
158     {
159         throw SimulatorException(SIMULATOR_OPERATION_NOT_ALLOWED,
160                                  "Discoverable state can not be changed when resource is started!");
161     }
162
163     if (state)
164         m_property = static_cast<OCResourceProperty>(m_property | OC_DISCOVERABLE);
165     else
166         m_property = static_cast<OCResourceProperty>(m_property ^ OC_DISCOVERABLE);
167 }
168
169 void SimulatorSingleResourceImpl::setObserverCallback(ObserverCallback callback)
170 {
171     VALIDATE_CALLBACK(callback)
172     m_observeCallback = callback;
173 }
174
175 void SimulatorSingleResourceImpl::setModelChangeCallback(ResourceModelUpdateCallback callback)
176 {
177     VALIDATE_CALLBACK(callback)
178     m_modelCallback = callback;
179 }
180
181 bool SimulatorSingleResourceImpl::isObservable() const
182 {
183     return ((m_property & OC_OBSERVABLE) == OC_OBSERVABLE);
184 }
185
186 bool SimulatorSingleResourceImpl::isDiscoverable() const
187 {
188     return ((m_property & OC_DISCOVERABLE) == OC_DISCOVERABLE);
189 }
190
191 bool SimulatorSingleResourceImpl::isStarted() const
192 {
193     return (nullptr != m_resourceHandle);
194 }
195
196 void SimulatorSingleResourceImpl::start()
197 {
198     std::lock_guard<std::recursive_mutex> lock(m_objectLock);
199     if (m_resourceHandle)
200     {
201         SIM_LOG(ILogger::ERROR, "[" << m_uri << "] " << "Resource already started!")
202         return;
203     }
204
205     if (m_uri.empty() || m_resourceType.empty())
206     {
207         throw SimulatorException(SIMULATOR_ERROR, "Incomplete data to start resource!");
208     }
209
210     typedef OCStackResult (*RegisterResource)(OCResourceHandle &, std::string &,
211             const std::string &, const std::string &, OC::EntityHandler, uint8_t);
212
213     invokeocplatform(static_cast<RegisterResource>(OC::OCPlatform::registerResource),
214                      m_resourceHandle, m_uri, m_resourceType, m_interfaces[0],
215                      std::bind(&SimulatorSingleResourceImpl::handleRequests,
216                                this, std::placeholders::_1), m_property);
217
218     for (size_t index = 1; m_interfaces.size() > 1 && index < m_interfaces.size(); index++)
219     {
220         typedef OCStackResult (*bindInterfaceToResource)(const OCResourceHandle &,
221                 const std::string &);
222
223         try
224         {
225             invokeocplatform(static_cast<bindInterfaceToResource>(
226                                  OC::OCPlatform::bindInterfaceToResource), m_resourceHandle,
227                              m_interfaces[index]);
228         }
229         catch (SimulatorException &e)
230         {
231             stop();
232             throw;
233         }
234     }
235 }
236
237 void SimulatorSingleResourceImpl::stop()
238 {
239     std::lock_guard<std::recursive_mutex> lock(m_objectLock);
240     if (!m_resourceHandle)
241     {
242         SIM_LOG(ILogger::ERROR, "[" << m_uri << "] " << "Resource is not started yet!")
243         return;
244     }
245
246     // Stop all the update automation of this resource
247     m_updateAutomationMgr.stopAll();
248
249     // Clear all the observers
250     removeAllObservers();
251
252     // Unregister the resource from stack
253     typedef OCStackResult (*UnregisterResource)(const OCResourceHandle &);
254
255     invokeocplatform(static_cast<UnregisterResource>(OC::OCPlatform::unregisterResource),
256                      m_resourceHandle);
257
258     m_resourceHandle = nullptr;
259 }
260
261 SimulatorResourceModel SimulatorSingleResourceImpl::getResourceModel()
262 {
263     std::lock_guard<std::recursive_mutex> lock(m_modelLock);
264     return m_resModel;
265 }
266
267 std::vector<ObserverInfo> SimulatorSingleResourceImpl::getObservers() const
268 {
269     return m_observersList;
270 }
271
272 void SimulatorSingleResourceImpl::notify(int observerID)
273 {
274     SimulatorResourceModel resModel;
275     {
276         std::lock_guard<std::recursive_mutex> lock(m_modelLock);
277         resModel = m_resModel;
278     }
279
280     notify(observerID, resModel);
281 }
282
283 void SimulatorSingleResourceImpl::notifyAll()
284 {
285     SimulatorResourceModel resModel;
286     {
287         std::lock_guard<std::recursive_mutex> lock(m_modelLock);
288         resModel = m_resModel;
289     }
290
291     notifyAll(resModel);
292 }
293
294 bool SimulatorSingleResourceImpl::getAttribute(const std::string &attrName,
295         SimulatorResourceAttribute &attribute)
296 {
297     std::lock_guard<std::recursive_mutex> modelLock(m_modelLock);
298     std::lock_guard<std::mutex> schemaLock(m_modelSchemaLock);
299
300     if (m_resModel.contains(attrName))
301     {
302         attribute.setName(attrName);
303         attribute.setValue(m_resModel.getAttributeValue(attrName));
304         attribute.setProperty(m_resModelSchema->get(attrName));
305         return true;
306     }
307
308     return false;
309 }
310
311 std::map<std::string, SimulatorResourceAttribute>
312 SimulatorSingleResourceImpl::getAttributes()
313 {
314     std::lock_guard<std::recursive_mutex> modelLock(m_modelLock);
315     std::lock_guard<std::mutex> schemaLock(m_modelSchemaLock);
316
317     std::map<std::string, SimulatorResourceAttribute> attributes;
318     for (auto &attributeEntry : m_resModel.getAttributeValues())
319     {
320         SimulatorResourceAttribute attribute(attributeEntry.first);
321         attribute.setValue(attributeEntry.second);
322
323         attribute.setProperty(m_resModelSchema->get(attributeEntry.first));
324         attributes[attributeEntry.first] = attribute;
325     }
326
327     return attributes;
328 }
329
330 bool SimulatorSingleResourceImpl::addAttribute(
331     const SimulatorResourceAttribute &attribute, bool notify)
332 {
333     if (attribute.getName().empty() || nullptr == attribute.getProperty())
334     {
335         return false;
336     }
337
338     // Add attribute to resource representation and its schema
339     std::lock_guard<std::recursive_mutex> modelLock(m_modelLock);
340     std::lock_guard<std::mutex> schemaLock(m_modelSchemaLock);
341
342     if (!m_resModel.add(attribute.getName(), attribute.getValue()))
343     {
344         return false;
345     }
346
347     m_resModelSchema->add(attribute.getName(), attribute.getProperty());
348
349     if (notify && isStarted())
350     {
351         try
352         {
353             notifyAll();
354         }
355         catch (SimulatorException &e)
356         {
357             SIM_LOG(ILogger::ERROR, "[" << m_uri << "] " << "Error when notifying the observers!")
358         }
359         notifyApp();
360     }
361
362     return true;
363 }
364
365 bool SimulatorSingleResourceImpl::updateAttributeValue(
366     const SimulatorResourceAttribute &attribute, bool notify)
367 {
368     if (attribute.getName().empty())
369     {
370         return false;
371     }
372
373     // Validate the new value against attribute schema property
374     std::lock_guard<std::mutex> schemaLock(m_modelSchemaLock);
375     auto property = m_resModelSchema->get(attribute.getName());
376     if (!(property->validate(attribute.getValue())))
377     {
378         return false;
379     }
380
381     // Update the attribute value
382     std::lock_guard<std::recursive_mutex> modelLock(m_modelLock);
383     if (!m_resModel.update(attribute.getName(), attribute.getValue()))
384     {
385         return false;
386     }
387
388     if (notify && isStarted())
389     {
390         try
391         {
392             notifyAll();
393         }
394         catch (SimulatorException &e)
395         {
396             SIM_LOG(ILogger::ERROR, "[" << m_uri << "] " << "Error when notifying the observers!")
397         }
398         notifyApp();
399     }
400
401     return true;
402 }
403
404 bool SimulatorSingleResourceImpl::removeAttribute(
405     const std::string &attrName, bool notify)
406 {
407     if (attrName.empty())
408     {
409         return false;
410     }
411
412     // Remove attribute from resource representation and its schema
413     std::lock_guard<std::recursive_mutex> modelLock(m_modelLock);
414     std::lock_guard<std::mutex> schemaLock(m_modelSchemaLock);
415
416     m_resModelSchema->remove(attrName);
417     if (!m_resModel.remove(attrName))
418     {
419         return false;
420     }
421
422     if (notify && isStarted())
423     {
424         try
425         {
426             notifyAll();
427         }
428         catch (SimulatorException &e)
429         {
430             SIM_LOG(ILogger::ERROR, "[" << m_uri << "] " << "Error when notifying the observers!")
431         }
432         notifyApp();
433     }
434
435     return true;
436 }
437
438 int SimulatorSingleResourceImpl::startResourceUpdation(AutoUpdateType type,
439         int updateInterval, AutoUpdateCompleteCallback callback)
440 {
441     VALIDATE_CALLBACK(callback)
442
443     std::lock_guard<std::recursive_mutex> lock(m_objectLock);
444     if (!m_resourceHandle)
445     {
446         throw SimulatorException(SIMULATOR_NO_RESOURCE, "Resource is not started!");
447     }
448
449     return m_updateAutomationMgr.startResourceAutomation(shared_from_this(), type,
450             updateInterval, callback);
451 }
452
453 int SimulatorSingleResourceImpl::startAttributeUpdation(const std::string &attrName,
454         AutoUpdateType type, int updateInterval, AutoUpdateCompleteCallback callback)
455 {
456     VALIDATE_CALLBACK(callback)
457
458     std::lock_guard<std::recursive_mutex> lock(m_objectLock);
459     if (!m_resourceHandle)
460     {
461         throw SimulatorException(SIMULATOR_NO_RESOURCE, "Resource is not started!");
462     }
463
464     return m_updateAutomationMgr.startAttributeAutomation(shared_from_this(), attrName,
465             type, updateInterval, callback);
466 }
467
468 std::vector<int> SimulatorSingleResourceImpl::getResourceUpdations()
469 {
470     return m_updateAutomationMgr.getResourceAutomationIds();
471 }
472
473 std::vector<int> SimulatorSingleResourceImpl::getAttributeUpdations()
474 {
475     return m_updateAutomationMgr.getAttributeAutomationIds();
476 }
477
478 void SimulatorSingleResourceImpl::stopUpdation(const int id)
479 {
480     m_updateAutomationMgr.stop(id);
481 }
482
483 void SimulatorSingleResourceImpl::notifyApp()
484 {
485     if (m_modelCallback)
486     {
487         m_modelCallback(m_uri, m_resModel);
488     }
489 }
490
491 void SimulatorSingleResourceImpl::notifyApp(const SimulatorResourceModel &resModel)
492 {
493     if (m_modelCallback)
494     {
495         m_modelCallback(m_uri, resModel);
496     }
497 }
498
499 void SimulatorSingleResourceImpl::setResourceModel(const SimulatorResourceModel &resModel)
500 {
501     std::lock_guard<std::recursive_mutex> lock(m_modelLock);
502     m_resModel = resModel;
503 }
504
505 void SimulatorSingleResourceImpl::setResourceModelSchema(
506     const std::shared_ptr<SimulatorResourceModelSchema> &resModelSchema)
507 {
508     std::lock_guard<std::mutex> lock(m_modelSchemaLock);
509     m_resModelSchema = resModelSchema;
510 }
511
512 void SimulatorSingleResourceImpl::setRequestModel(
513     const std::unordered_map<std::string, std::shared_ptr<RequestModel>> &requestModels)
514 {
515     m_requestModels = requestModels;
516 }
517
518 bool SimulatorSingleResourceImpl::updateResourceModel(const SimulatorResourceModel &reqResModel,
519         SimulatorResourceModel &updatedResModel, bool overwrite, bool notify)
520 {
521     std::lock_guard<std::mutex> schemaLock(m_modelSchemaLock);
522     std::lock_guard<std::recursive_mutex> modelLock(m_modelLock);
523
524     size_t reqModelSize = reqResModel.size();
525     SimulatorResourceModel tempResModel;
526
527     for (auto &attributeName : m_resModel.getAttributeNameSet())
528     {
529         // Break the loop if update request model has no more attributes for validation.
530         if (!reqModelSize)
531         {
532             break;
533         }
534
535         // Check attribute presence criteria
536         if (!reqResModel.contains(attributeName))
537         {
538             if (overwrite)
539                 return false;
540             continue;
541         }
542
543         reqModelSize--;
544
545         // Value type check
546         if (!(m_resModel.getType(attributeName) == reqResModel.getType(attributeName)))
547         {
548             return false;
549         }
550
551         // Validate the new value against attribute schema property
552         auto property = m_resModelSchema->get(attributeName);
553         if (!(property->validate(reqResModel.getAttributeValue(attributeName))))
554         {
555             return false;
556         }
557
558         tempResModel.add(attributeName, reqResModel.getAttributeValue(attributeName));
559     }
560
561     // Validation is success, now update the attribute values.
562     for (auto &valueEntry : tempResModel.getAttributeValues())
563     {
564         m_resModel.update(valueEntry.first, valueEntry.second);
565     }
566
567     updatedResModel = m_resModel;
568
569     if (notify && isStarted())
570     {
571         try
572         {
573             notifyAll();
574         }
575         catch (SimulatorException &e)
576         {
577             SIM_LOG(ILogger::ERROR, "[" << m_uri << "] " << "Error when notifying the observers!")
578         }
579         notifyApp();
580     }
581
582     return true;
583 }
584
585 void SimulatorSingleResourceImpl::notify(int observerID, const SimulatorResourceModel &resModel)
586 {
587     std::lock_guard<std::recursive_mutex> lock(m_objectLock);
588     if (!m_resourceHandle)
589         return;
590
591     std::shared_ptr<OC::OCResourceResponse> response(new OC::OCResourceResponse);
592     response->setErrorCode(200);
593     response->setResponseResult(OC_EH_OK);
594     response->setResourceRepresentation(resModel.asOCRepresentation(), m_interfaces[0]);
595
596     OC::ObservationIds observers;
597     observers.push_back(observerID);
598
599     typedef OCStackResult (*NotifyListOfObservers)(OCResourceHandle, OC::ObservationIds &,
600             const std::shared_ptr<OC::OCResourceResponse>);
601
602     invokeocplatform(static_cast<NotifyListOfObservers>(OC::OCPlatform::notifyListOfObservers),
603                      m_resourceHandle, observers, response);
604 }
605
606 void SimulatorSingleResourceImpl::notifyAll(const SimulatorResourceModel &resModel)
607 {
608     std::lock_guard<std::recursive_mutex> lock(m_objectLock);
609     if (!m_resourceHandle)
610         return;
611
612     if (!m_observersList.size())
613         return;
614
615     std::shared_ptr<OC::OCResourceResponse> response(new OC::OCResourceResponse);
616     response->setErrorCode(200);
617     response->setResponseResult(OC_EH_OK);
618     response->setResourceRepresentation(resModel.asOCRepresentation(), m_interfaces[0]);
619
620     OC::ObservationIds observers;
621     for (auto &observer : m_observersList)
622         observers.push_back(observer.id);
623
624     typedef OCStackResult (*NotifyListOfObservers)(OCResourceHandle, OC::ObservationIds &,
625             const std::shared_ptr<OC::OCResourceResponse>);
626
627     invokeocplatform(static_cast<NotifyListOfObservers>(OC::OCPlatform::notifyListOfObservers),
628                      m_resourceHandle, observers, response);
629 }
630
631 void SimulatorSingleResourceImpl::setCommonProperties(OC::OCRepresentation &ocResRep)
632 {
633     std::lock_guard<std::recursive_mutex> lock(m_objectLock);
634     ocResRep.setValue("rt", m_resourceType);
635     ocResRep.setValue("if", m_interfaces);
636     ocResRep.setValue("n", m_name);
637 }
638
639 OCEntityHandlerResult SimulatorSingleResourceImpl::handleRequests(
640     std::shared_ptr<OC::OCResourceRequest> request)
641 {
642     if (!request)
643     {
644         OC_LOG(ERROR, TAG, "Request received from stack is null!");
645         return OC_EH_ERROR;
646     }
647
648     OCEntityHandlerResult result = OC_EH_OK;
649
650     // Handle GET, PUT, POST and DELETE requests
651     if (OC::RequestHandlerFlag::RequestFlag & request->getRequestHandlerFlag())
652     {
653         {
654             OC::OCRepresentation rep = request->getResourceRepresentation();
655             std::string payload = getPayloadString(rep);
656             SIM_LOG(ILogger::INFO, "[" << m_uri << "] " << request->getRequestType()
657                     << " request received. \n**Payload details**\n" << payload)
658         }
659
660         if ("GET" == request->getRequestType())
661         {
662             result = handleGET(request);
663         }
664         else if ("PUT" == request->getRequestType())
665         {
666             result = handlePUT(request);
667         }
668         else if ("POST" == request->getRequestType())
669         {
670             result = handlePOST(request);
671         }
672         else if ("DELETE" == request->getRequestType())
673         {
674             result = handleDELETE(request);
675         }
676     }
677
678     // Handle OBSERVE requests
679     if ((OC::RequestHandlerFlag::ObserverFlag & request->getRequestHandlerFlag())
680         && isObservable())
681     {
682         OC::ObservationInfo observationInfo = request->getObservationInfo();
683         if (OC::ObserveAction::ObserveRegister == observationInfo.action)
684         {
685             addObserver(observationInfo);
686             SIM_LOG(ILogger::INFO, "[" << m_uri << "] Observer added [id: "
687                     << (int)observationInfo.obsId << ", address: " << observationInfo.address
688                     << ", port: " << observationInfo.port << "].");
689         }
690         else if (OC::ObserveAction::ObserveUnregister == observationInfo.action)
691         {
692             removeObserver(observationInfo);
693             SIM_LOG(ILogger::INFO, "[" << m_uri << "] Observer removed [id: "
694                     << (int)observationInfo.obsId << ", address: " << observationInfo.address
695                     << ", port: " << observationInfo.port << "].");
696         }
697     }
698
699     return result;
700 }
701
702 void SimulatorSingleResourceImpl::addObserver(const OC::ObservationInfo &ocObserverInfo)
703 {
704     ObserverInfo info {ocObserverInfo.obsId, ocObserverInfo.address, ocObserverInfo.port};
705     m_observersList.push_back(info);
706
707     if (m_observeCallback)
708         m_observeCallback(m_uri, ObservationStatus::REGISTER, info);
709 }
710
711 void SimulatorSingleResourceImpl::removeObserver(const OC::ObservationInfo &ocObserverInfo)
712 {
713     bool found = false;
714     ObserverInfo info;
715     for (auto iter = m_observersList.begin(); iter != m_observersList.end(); iter++)
716     {
717         if ((*iter).id == ocObserverInfo.obsId)
718         {
719             info = *iter;
720             found = true;
721             m_observersList.erase(iter);
722             break;
723         }
724     }
725
726     if (found && m_observeCallback)
727         m_observeCallback(m_uri, ObservationStatus::UNREGISTER, info);
728 }
729
730 void SimulatorSingleResourceImpl::removeAllObservers()
731 {
732     std::vector<ObserverInfo> observerList = m_observersList;
733     m_observersList.clear();
734     for (size_t index = 0; index < observerList.size(); index++)
735     {
736         if (m_observeCallback)
737             m_observeCallback(m_uri, ObservationStatus::UNREGISTER, observerList[index]);
738     }
739 }
740
741 OCEntityHandlerResult SimulatorSingleResourceImpl::handleGET(
742     const std::shared_ptr<OC::OCResourceRequest> &request)
743 {
744     // Check if resource support GET request
745     if (m_requestModels.end() == m_requestModels.find("GET"))
746     {
747         SIM_LOG(ILogger::ERROR, "[" << m_uri << "] "
748                 << "Resource does not support GET request!")
749         return sendResponse(request, 405, OC_EH_ERROR);
750     }
751
752     // Handling interface query parameter "if"
753     auto interfaceType = m_interfaces[0];
754     auto requestQueryParams = request->getQueryParameters();
755     if (requestQueryParams.end() != requestQueryParams.find("if"))
756     {
757         interfaceType = requestQueryParams["if"];
758     }
759
760     if (!isValidInterface(interfaceType, "GET"))
761     {
762         SIM_LOG(ILogger::ERROR, "[" << m_uri << "] "
763                 << "GET request received on invalid interface : " << interfaceType)
764         return OC_EH_ERROR;
765     }
766
767     OC::OCRepresentation resourceRep = getResourceModel().asOCRepresentation();
768
769     // Add common properties to resource representation if interface is
770     // neither "oic.if.a" nor "oic.if.s".
771     if (OC::ACTUATOR_INTERFACE != interfaceType &&
772         OC::SENSOR_INTERFACE != interfaceType)
773     {
774         setCommonProperties(resourceRep);
775     }
776
777     return sendResponse(request, 200, OC_EH_OK, resourceRep, interfaceType);
778 }
779
780 OCEntityHandlerResult SimulatorSingleResourceImpl::handlePUT(
781     const std::shared_ptr<OC::OCResourceRequest> &request)
782 {
783     // Check if resource support PUT request
784     if (m_requestModels.end() == m_requestModels.find("PUT"))
785     {
786         SIM_LOG(ILogger::ERROR, "[" << m_uri << "] "
787                 << "Resource does not support PUT request!")
788         return sendResponse(request, 405, OC_EH_ERROR);
789     }
790
791     // Handling interface query parameter "if"
792     auto interfaceType = m_interfaces[0];
793     auto requestQueryParams = request->getQueryParameters();
794     if (requestQueryParams.end() != requestQueryParams.find("if"))
795     {
796         interfaceType = requestQueryParams["if"];
797     }
798
799     if (!isValidInterface(interfaceType, "PUT"))
800     {
801         SIM_LOG(ILogger::ERROR, "[" << m_uri << "] "
802                 << "PUT request received on invalid interface : " << interfaceType)
803         return OC_EH_ERROR;
804     }
805
806     OC::OCRepresentation reqOcRep = request->getResourceRepresentation();
807     SimulatorResourceModel reqResModel = SimulatorResourceModel::build(reqOcRep);
808     SimulatorResourceModel updatedResModel;
809     if (true == updateResourceModel(reqResModel, updatedResModel, true, false))
810     {
811         auto ocRep = updatedResModel.asOCRepresentation();
812         auto result = sendResponse(request, 200, OC_EH_OK,
813                                    ocRep, m_interfaces[0]);
814         notifyApp(updatedResModel);
815         try
816         {
817             notifyAll();
818         }
819         catch (SimulatorException &e)
820         {
821             SIM_LOG(ILogger::ERROR, "[" << m_uri << "] "
822                     << "Error when notifying the observers!")
823         }
824
825         return result;
826     }
827
828     SIM_LOG(ILogger::ERROR, "[" << m_uri << "] " << "Updating resource representation failed!")
829     return sendResponse(request, 400, OC_EH_ERROR);
830 }
831
832 OCEntityHandlerResult SimulatorSingleResourceImpl::handlePOST(
833     const std::shared_ptr<OC::OCResourceRequest> &request)
834 {
835     // Check if resource support PUT request
836     if (m_requestModels.end() == m_requestModels.find("POST"))
837     {
838         SIM_LOG(ILogger::ERROR, "[" << m_uri << "] "
839                 << "Resource does not support POST request!")
840         return sendResponse(request, 405, OC_EH_ERROR);
841     }
842
843     // Handling interface query parameter "if"
844     auto interfaceType = m_interfaces[0];
845     auto requestQueryParams = request->getQueryParameters();
846     if (requestQueryParams.end() != requestQueryParams.find("if"))
847     {
848         interfaceType = requestQueryParams["if"];
849     }
850
851     if (!isValidInterface(interfaceType, "POST"))
852     {
853         SIM_LOG(ILogger::ERROR, "[" << m_uri << "] "
854                 << "POST request received on invalid interface : " << interfaceType)
855         return OC_EH_ERROR;
856     }
857
858     OC::OCRepresentation reqOcRep = request->getResourceRepresentation();
859     SimulatorResourceModel reqResModel = SimulatorResourceModel::build(reqOcRep);
860     SimulatorResourceModel updatedResModel;
861     if (true == updateResourceModel(reqResModel, updatedResModel, false, false))
862     {
863         auto ocRep = updatedResModel.asOCRepresentation();
864         auto result = sendResponse(request, 200, OC_EH_OK,
865                                    ocRep, m_interfaces[0]);
866         notifyApp(updatedResModel);
867         try
868         {
869             notifyAll();
870         }
871         catch (SimulatorException &e)
872         {
873             SIM_LOG(ILogger::ERROR, "[" << m_uri << "] "
874                     << "Error when notifying the observers!")
875         }
876
877         return result;
878     }
879
880     SIM_LOG(ILogger::ERROR, "[" << m_uri << "] " << "Updating resource representation failed!")
881     return sendResponse(request, 400, OC_EH_ERROR);
882 }
883
884 OCEntityHandlerResult SimulatorSingleResourceImpl::handleDELETE(
885     const std::shared_ptr<OC::OCResourceRequest> &request)
886 {
887     SIM_LOG(ILogger::ERROR, "[" << m_uri << "] "
888             << "Resource does not support DELETE request!")
889     return sendResponse(request, 405, OC_EH_ERROR);;
890 }
891
892 bool SimulatorSingleResourceImpl::isValidInterface(const std::string &interfaceType,
893         const std::string &requestType)
894 {
895     // Is this OIC defined interface ?
896     if (false ==
897         OCInterfaceDetails::getInstance()->isRequestSupported(interfaceType, requestType))
898     {
899         return false;
900     }
901
902     // Does resource support this interface ?
903     std::lock_guard<std::recursive_mutex> lock(m_objectLock);
904     if (m_interfaces.end() ==
905         std::find(m_interfaces.begin(), m_interfaces.end(), interfaceType))
906     {
907         return false;
908     }
909
910     return true;
911 }
912
913 OCEntityHandlerResult SimulatorSingleResourceImpl::sendResponse(
914     const std::shared_ptr<OC::OCResourceRequest> &request, const int errorCode,
915     OCEntityHandlerResult responseResult)
916 {
917     std::shared_ptr<OC::OCResourceResponse> response(new OC::OCResourceResponse());
918     response->setRequestHandle(request->getRequestHandle());
919     response->setResourceHandle(request->getResourceHandle());
920     response->setErrorCode(errorCode);
921     response->setResponseResult(responseResult);
922     if (OC_STACK_OK != OC::OCPlatform::sendResponse(response))
923     {
924         SIM_LOG(ILogger::ERROR, "[" << m_uri << "] Failed to send response for " <<
925             request->getRequestType() <<" request!")
926         return OC_EH_ERROR;
927     }
928
929     SIM_LOG(ILogger::INFO, "[" << m_uri << "] Sent response for " <<
930         request->getRequestType() << " request.")
931
932     return OC_EH_OK;
933 }
934
935 OCEntityHandlerResult SimulatorSingleResourceImpl::sendResponse(
936     const std::shared_ptr<OC::OCResourceRequest> &request, const int errorCode,
937     OCEntityHandlerResult responseResult, OC::OCRepresentation &payload,
938     const std::string &interfaceType)
939 {
940     std::shared_ptr<OC::OCResourceResponse> response(new OC::OCResourceResponse());
941     response->setRequestHandle(request->getRequestHandle());
942     response->setResourceHandle(request->getResourceHandle());
943     response->setErrorCode(errorCode);
944     response->setResponseResult(responseResult);
945     response->setResourceRepresentation(payload, interfaceType);
946     if (OC_STACK_OK != OC::OCPlatform::sendResponse(response))
947     {
948         SIM_LOG(ILogger::ERROR, "[" << m_uri << "] Failed to send response for " <<
949             request->getRequestType() <<" request!")
950         return OC_EH_ERROR;
951     }
952
953     SIM_LOG(ILogger::INFO, "[" << m_uri << "] Sent response for " <<
954         request->getRequestType() << " request \n\n" <<
955         "**Payload details**" << getPayloadString(payload))
956
957     return OC_EH_OK;
958 }