1 /******************************************************************
3 * Copyright 2015 Samsung Electronics All Rights Reserved.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 ******************************************************************/
21 #include "simulator_collection_resource_impl.h"
22 #include "simulator_utils.h"
23 #include "simulator_logger.h"
26 #define TAG "SIM_COLLECTION_RESOURCE"
28 SimulatorCollectionResourceImpl::SimulatorCollectionResourceImpl()
29 : m_type(SimulatorResource::Type::COLLECTION_RESOURCE),
30 m_interfaces {OC::DEFAULT_INTERFACE, OC::LINK_INTERFACE},
31 m_resourceHandle(NULL)
33 m_property = static_cast<OCResourceProperty>(OC_DISCOVERABLE | OC_OBSERVABLE);
36 std::string SimulatorCollectionResourceImpl::getName() const
41 SimulatorResource::Type SimulatorCollectionResourceImpl::getType() const
46 std::string SimulatorCollectionResourceImpl::getURI() const
51 std::string SimulatorCollectionResourceImpl::getResourceType() const
53 return m_resourceType;
56 std::vector<std::string> SimulatorCollectionResourceImpl::getInterface() const
61 void SimulatorCollectionResourceImpl::setInterface(const std::vector<std::string> &interfaces)
63 m_interfaces = interfaces;
66 void SimulatorCollectionResourceImpl::setName(const std::string &name)
68 VALIDATE_INPUT(name.empty(), "Name is empty!")
70 std::lock_guard<std::recursive_mutex> lock(m_objectLock);
73 throw SimulatorException(SIMULATOR_OPERATION_NOT_ALLOWED,
74 "Name can not be set when collection is started!");
80 void SimulatorCollectionResourceImpl::setURI(const std::string &uri)
82 VALIDATE_INPUT(uri.empty(), "Uri is empty!")
84 std::lock_guard<std::recursive_mutex> lock(m_objectLock);
87 throw SimulatorException(SIMULATOR_OPERATION_NOT_ALLOWED,
88 "URI can not be set when collection is started!");
94 void SimulatorCollectionResourceImpl::setResourceType(const std::string &resourceType)
96 VALIDATE_INPUT(resourceType.empty(), "Resource type is empty!")
98 std::lock_guard<std::recursive_mutex> lock(m_objectLock);
101 throw SimulatorException(SIMULATOR_OPERATION_NOT_ALLOWED,
102 "Resource type can not be set when collection is started!");
105 m_resourceType = resourceType;
108 void SimulatorCollectionResourceImpl::addInterface(std::string interfaceType)
110 VALIDATE_INPUT(interfaceType.empty(), "Interface type is empty!")
112 if (interfaceType == OC::GROUP_INTERFACE)
114 throw NoSupportException("Collection resource does not support this interface type!");
117 std::lock_guard<std::recursive_mutex> lock(m_objectLock);
118 if (m_resourceHandle)
120 throw SimulatorException(SIMULATOR_OPERATION_NOT_ALLOWED,
121 "Interface type can not be set when resource is started!");
124 auto found = std::find(m_interfaces.begin(), m_interfaces.end(), interfaceType);
125 if (found != m_interfaces.end())
126 m_interfaces.push_back(interfaceType);
129 void SimulatorCollectionResourceImpl::setObservable(bool state)
131 std::lock_guard<std::recursive_mutex> lock(m_objectLock);
132 if (m_resourceHandle)
134 throw SimulatorException(SIMULATOR_OPERATION_NOT_ALLOWED,
135 "Observation state can not be changed when resource is started!");
139 m_property = static_cast<OCResourceProperty>(m_property | OC_OBSERVABLE);
141 m_property = static_cast<OCResourceProperty>(m_property ^ OC_OBSERVABLE);
144 void SimulatorCollectionResourceImpl::setObserverCallback(ObserverCallback callback)
146 VALIDATE_CALLBACK(callback)
147 m_observeCallback = callback;
150 void SimulatorCollectionResourceImpl::setModelChangeCallback(ResourceModelChangedCallback callback)
152 VALIDATE_CALLBACK(callback)
153 m_modelCallback = callback;
156 bool SimulatorCollectionResourceImpl::isObservable()
158 return (m_property & OC_OBSERVABLE);
161 bool SimulatorCollectionResourceImpl::isStarted()
163 return (nullptr != m_resourceHandle);
166 void SimulatorCollectionResourceImpl::start()
168 std::lock_guard<std::recursive_mutex> lock(m_objectLock);
169 if (m_resourceHandle)
171 throw SimulatorException(SIMULATOR_ERROR, "Collection already registered!");
174 if (m_uri.empty() || m_resourceType.empty())
176 throw SimulatorException(SIMULATOR_ERROR, "Found incomplete data to start resource!");
179 typedef OCStackResult (*RegisterResource)(OCResourceHandle &, std::string &, const std::string &,
180 const std::string &, OC::EntityHandler, uint8_t);
182 invokeocplatform(static_cast<RegisterResource>(OC::OCPlatform::registerResource),
183 m_resourceHandle, m_uri, m_resourceType, m_interfaces[0],
184 std::bind(&SimulatorCollectionResourceImpl::handleRequests,
185 this, std::placeholders::_1), m_property);
187 for (size_t index = 1; m_interfaces.size() > 1 && index < m_interfaces.size(); index++)
189 typedef OCStackResult (*bindInterfaceToResource)(const OCResourceHandle &,
190 const std::string &);
194 invokeocplatform(static_cast<bindInterfaceToResource>(
195 OC::OCPlatform::bindInterfaceToResource), m_resourceHandle,
196 m_interfaces[index]);
198 catch (SimulatorException &e)
206 void SimulatorCollectionResourceImpl::stop()
208 std::lock_guard<std::recursive_mutex> lock(m_objectLock);
209 if (!m_resourceHandle)
212 typedef OCStackResult (*UnregisterResource)(const OCResourceHandle &);
214 invokeocplatform(static_cast<UnregisterResource>(OC::OCPlatform::unregisterResource),
217 m_resourceHandle = nullptr;
220 SimulatorResourceModel SimulatorCollectionResourceImpl::getResourceModel()
222 std::lock_guard<std::mutex> lock(m_modelLock);
226 void SimulatorCollectionResourceImpl::setResourceModel(const SimulatorResourceModel &resModel)
228 std::lock_guard<std::mutex> lock(m_modelLock);
229 m_resModel = resModel;
232 void SimulatorCollectionResourceImpl::setActionType(std::map<RAML::ActionType, RAML::ActionPtr> &actionType)
234 m_actionTypes = actionType;
237 std::vector<ObserverInfo> SimulatorCollectionResourceImpl::getObserversList()
239 return m_observersList;
242 void SimulatorCollectionResourceImpl::notify(int id)
244 std::lock_guard<std::recursive_mutex> lock(m_objectLock);
245 if (!m_resourceHandle)
248 OC::ObservationIds observers {static_cast<OCObservationId>(id)};
249 sendNotification(observers);
252 void SimulatorCollectionResourceImpl::notifyAll()
254 std::lock_guard<std::recursive_mutex> lock(m_objectLock);
255 if (!m_resourceHandle)
258 if (!m_observersList.size())
261 OC::ObservationIds observers;
262 for (auto &observer : m_observersList)
263 observers.push_back(observer.id);
264 sendNotification(observers);
267 std::vector<std::string> SimulatorCollectionResourceImpl::getSupportedResources()
269 return m_supportedTypes;
272 void SimulatorCollectionResourceImpl::addChildResource(SimulatorResourceSP &resource)
274 VALIDATE_INPUT(!resource, "Invalid child resource!")
276 std::lock_guard<std::mutex> lock(m_childResourcesLock);
277 if (m_childResources.end() != m_childResources.find(resource->getURI()))
279 throw SimulatorException(SIMULATOR_ERROR, "Child resource with same URI is already exisit!");
282 m_childResources[resource->getURI()] = resource;
285 // Notify application and observers
287 m_modelCallback(m_uri, m_resModel);
291 void SimulatorCollectionResourceImpl::removeChildResource(SimulatorResourceSP &resource)
293 VALIDATE_INPUT(!resource, "Invalid child resource!")
295 std::lock_guard<std::mutex> lock(m_childResourcesLock);
296 if (m_childResources.end() == m_childResources.find(resource->getURI()))
298 throw SimulatorException(SIMULATOR_ERROR, "Child resource not found in collection!");
301 removeLink(resource->getURI());
302 m_childResources.erase(m_childResources.find(resource->getURI()));
304 // Notify application and observers
306 m_modelCallback(m_uri, m_resModel);
310 void SimulatorCollectionResourceImpl::removeChildResource(const std::string &uri)
312 VALIDATE_INPUT(uri.empty(), "Uri is empty!")
314 std::lock_guard<std::mutex> lock(m_childResourcesLock);
315 if (m_childResources.end() == m_childResources.find(uri))
317 throw SimulatorException(SIMULATOR_ERROR, "Child resource not found in collection!");
321 m_childResources.erase(m_childResources.find(uri));
323 // Notify application and observers
325 m_modelCallback(m_uri, m_resModel);
329 std::vector<SimulatorResourceSP> SimulatorCollectionResourceImpl::getChildResources()
331 std::lock_guard<std::mutex> lock(m_childResourcesLock);
333 std::vector<SimulatorResourceSP> result;
334 for (auto &entry : m_childResources)
335 result.push_back(entry.second);
340 OCEntityHandlerResult SimulatorCollectionResourceImpl::handleRequests(
341 std::shared_ptr<OC::OCResourceRequest> request)
346 if (OC::RequestHandlerFlag::RequestFlag & request->getRequestHandlerFlag())
349 OC::OCRepresentation rep = request->getResourceRepresentation();
350 std::string payload = getPayloadString(rep);
351 SIM_LOG(ILogger::INFO, "[" << m_name << "] " << request->getRequestType()
352 << " request received. \n**Payload details**\n" << payload)
355 // Handover the request to appropriate interface handler
356 std::string interfaceType(OC::DEFAULT_INTERFACE);
357 OC::QueryParamsMap queryParams = request->getQueryParameters();
358 if (queryParams.end() != queryParams.find("if"))
359 interfaceType = queryParams["if"];
361 std::shared_ptr<OC::OCResourceResponse> response;
362 if (interfaceType == OC::DEFAULT_INTERFACE)
364 response = requestOnBaseLineInterface(request);
366 else if (interfaceType == OC::LINK_INTERFACE)
368 response = requestOnLinkListInterface(request);
370 else if (interfaceType == OC::BATCH_INTERFACE)
372 response = requestOnBatchInterface(request);
375 // Send response if the request handled by resource
378 if (OC_STACK_OK != OC::OCPlatform::sendResponse(response))
383 SIM_LOG(ILogger::ERROR, "[" << m_name << "] " << "Unsupported request received!")
388 if (OC::RequestHandlerFlag::ObserverFlag & request->getRequestHandlerFlag())
392 SIM_LOG(ILogger::INFO, "[" << m_uri << "] OBSERVE request received")
393 SIM_LOG(ILogger::INFO, "[" << m_uri << "] Sending error as resource is in unobservable state!")
397 OC::ObservationInfo observationInfo = request->getObservationInfo();
398 if (OC::ObserveAction::ObserveRegister == observationInfo.action)
400 SIM_LOG(ILogger::INFO, "[" << m_uri << "] OBSERVE REGISTER request received");
402 ObserverInfo info {observationInfo.obsId, observationInfo.address, observationInfo.port};
403 m_observersList.push_back(info);
405 if (m_observeCallback)
406 m_observeCallback(m_uri, ObservationStatus::REGISTER, info);
408 else if (OC::ObserveAction::ObserveUnregister == observationInfo.action)
410 SIM_LOG(ILogger::INFO, "[" << m_uri << "] OBSERVE UNREGISTER request received");
413 for (auto iter = m_observersList.begin(); iter != m_observersList.end(); iter++)
415 if ((info = *iter), info.id == observationInfo.obsId)
417 m_observersList.erase(iter);
422 if (m_observeCallback)
423 m_observeCallback(m_uri, ObservationStatus::UNREGISTER, info);
430 std::shared_ptr<OC::OCResourceResponse> SimulatorCollectionResourceImpl::requestOnBaseLineInterface(
431 std::shared_ptr<OC::OCResourceRequest> request)
433 std::shared_ptr<OC::OCResourceResponse> response;
435 RAML::ActionType type = getActionType(request->getRequestType());
437 if (!m_actionTypes.empty())
439 if (m_actionTypes.end() == m_actionTypes.find(type))
443 if ("GET" == request->getRequestType())
445 // Construct the representation
446 OC::OCRepresentation ocRep = m_resModel.getOCRepresentation();
447 response = std::make_shared<OC::OCResourceResponse>();
448 response->setErrorCode(200);
449 response->setResponseResult(OC_EH_OK);
450 response->setResourceRepresentation(ocRep);
451 std::string resPayload = getPayloadString(ocRep);
452 SIM_LOG(ILogger::INFO, "[" << m_uri <<
453 "] Sending response for GET request. \n**Payload details**" << resPayload)
456 // TODO: Handle PUT, POST and DELETE requests
460 response->setRequestHandle(request->getRequestHandle());
461 response->setResourceHandle(request->getResourceHandle());
467 std::shared_ptr<OC::OCResourceResponse> SimulatorCollectionResourceImpl::requestOnLinkListInterface(
468 std::shared_ptr<OC::OCResourceRequest> request)
470 std::lock_guard<std::mutex> lock(m_childResourcesLock);
471 std::shared_ptr<OC::OCResourceResponse> response;
473 RAML::ActionType type = getActionType(request->getRequestType());
475 if (!m_actionTypes.empty())
477 if (m_actionTypes.end() == m_actionTypes.find(type))
481 if ("GET" == request->getRequestType())
483 // Construct the representation
484 OC::OCRepresentation ocRep;
485 std::vector<OC::OCRepresentation> links;
486 for (auto &entry : m_childResources)
488 OC::OCRepresentation oicLink;
489 oicLink.setValue("href", entry.second->getURI());
490 oicLink.setValue("rt", entry.second->getResourceType());
491 oicLink.setValue("if", entry.second->getInterface()[0]);
492 links.push_back(oicLink);
495 ocRep.setValue("links", links);
497 response = std::make_shared<OC::OCResourceResponse>();
498 response->setRequestHandle(request->getRequestHandle());
499 response->setResourceHandle(request->getResourceHandle());
500 response->setErrorCode(200);
501 response->setResponseResult(OC_EH_OK);
502 response->setResourceRepresentation(ocRep);
503 std::string resPayload = getPayloadString(ocRep);
504 SIM_LOG(ILogger::INFO, "[" << m_uri <<
505 "] Sending response for GET request. \n**Payload details**" << resPayload)
511 std::shared_ptr<OC::OCResourceResponse> SimulatorCollectionResourceImpl::requestOnBatchInterface(
512 std::shared_ptr<OC::OCResourceRequest>)
514 // TODO: Handle this interface
518 void SimulatorCollectionResourceImpl::sendNotification(OC::ObservationIds &observers)
520 std::lock_guard<std::recursive_mutex> lock(m_objectLock);
521 std::shared_ptr<OC::OCResourceResponse> response(new OC::OCResourceResponse());
522 response->setErrorCode(200);
523 response->setResponseResult(OC_EH_OK);
525 OC::OCRepresentation ocRep = m_resModel.getOCRepresentation();
526 response->setResourceRepresentation(ocRep, OC::DEFAULT_INTERFACE);
528 typedef OCStackResult (*NotifyListOfObservers)(OCResourceHandle, OC::ObservationIds &,
529 const std::shared_ptr<OC::OCResourceResponse>);
531 invokeocplatform(static_cast<NotifyListOfObservers>(OC::OCPlatform::notifyListOfObservers),
532 m_resourceHandle, observers, response);
535 void SimulatorCollectionResourceImpl::addLink(SimulatorResourceSP &resource)
537 std::lock_guard<std::mutex> lock(m_modelLock);
538 if (!m_resModel.containsAttribute("links"))
541 // Create new OIC Link
542 SimulatorResourceModel newLink;
543 newLink.add("href", resource->getURI());
544 newLink.add("rt", resource->getResourceType());
545 newLink.add("if", resource->getInterface()[0]);
547 // Add OIC Link if it is not present
549 std::vector<SimulatorResourceModel> links =
550 m_resModel.get<std::vector<SimulatorResourceModel>>("links");
551 for (auto &link : links)
553 std::string linkURI = link.get<std::string>("href");
554 if (linkURI == resource->getURI())
563 links.push_back(newLink);
564 m_resModel.updateValue("links", links);
568 void SimulatorCollectionResourceImpl::removeLink(std::string uri)
570 std::lock_guard<std::mutex> lock(m_modelLock);
571 if (!m_resModel.containsAttribute("links"))
574 // Add OIC Link if it is not present
575 std::vector<SimulatorResourceModel> links =
576 m_resModel.get<std::vector<SimulatorResourceModel>>("links");
577 for (size_t i = 0; i < links.size(); i++)
579 std::string linkURI = links[i].get<std::string>("href");
582 links.erase(links.begin() + i);
583 m_resModel.updateValue("links", links);
589 RAML::ActionType SimulatorCollectionResourceImpl::getActionType(std::string requestType)
591 if (!requestType.compare("GET"))
592 return RAML::ActionType::GET;
594 if (!requestType.compare("PUT"))
595 return RAML::ActionType::PUT;
597 if (!requestType.compare("POST"))
598 return RAML::ActionType::POST;
600 if (!requestType.compare("DELETE"))
601 return RAML::ActionType::DELETE;
603 return RAML::ActionType::NONE;