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