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_resourceHandle(NULL),
31 m_interfaces {OC::DEFAULT_INTERFACE, OC::LINK_INTERFACE}
33 m_property = static_cast<OCResourceProperty>(OC_DISCOVERABLE | OC_OBSERVABLE);
35 std::vector<SimulatorResourceModel> links;
36 m_resModel.add("links", links);
39 std::string SimulatorCollectionResourceImpl::getName() const
44 SimulatorResource::Type SimulatorCollectionResourceImpl::getType() const
49 std::string SimulatorCollectionResourceImpl::getURI() const
54 std::string SimulatorCollectionResourceImpl::getResourceType() const
56 return m_resourceType;
59 std::vector<std::string> SimulatorCollectionResourceImpl::getInterface() const
64 void SimulatorCollectionResourceImpl::setInterface(const std::vector<std::string> &interfaces)
66 if (!interfaces.empty())
67 m_interfaces = interfaces;
70 void SimulatorCollectionResourceImpl::setName(const std::string &name)
72 VALIDATE_INPUT(name.empty(), "Name is empty!")
77 void SimulatorCollectionResourceImpl::setURI(const std::string &uri)
79 VALIDATE_INPUT(uri.empty(), "Uri is empty!")
81 std::lock_guard<std::recursive_mutex> lock(m_objectLock);
84 throw SimulatorException(SIMULATOR_OPERATION_NOT_ALLOWED,
85 "URI can not be set when collection is started!");
91 void SimulatorCollectionResourceImpl::setResourceType(const std::string &resourceType)
93 VALIDATE_INPUT(resourceType.empty(), "Resource type is empty!")
95 std::lock_guard<std::recursive_mutex> lock(m_objectLock);
98 throw SimulatorException(SIMULATOR_OPERATION_NOT_ALLOWED,
99 "Resource type can not be set when collection is started!");
102 m_resourceType = resourceType;
105 void SimulatorCollectionResourceImpl::addInterface(const std::string &interfaceType)
107 VALIDATE_INPUT(interfaceType.empty(), "Interface type is empty!")
109 if (interfaceType == OC::LINK_INTERFACE
110 || interfaceType == OC::BATCH_INTERFACE
111 || interfaceType == OC::DEFAULT_INTERFACE)
113 if (m_interfaces.end() != std::find(m_interfaces.begin(), m_interfaces.end(), interfaceType))
115 SIM_LOG(ILogger::ERROR, "Resource already supports " << interfaceType << " interface!");
119 std::lock_guard<std::recursive_mutex> lock(m_objectLock);
120 typedef OCStackResult (*bindInterfaceToResource)(const OCResourceHandle &,
121 const std::string &);
125 invokeocplatform(static_cast<bindInterfaceToResource>(
126 OC::OCPlatform::bindInterfaceToResource), m_resourceHandle,
129 catch (SimulatorException &e)
136 throw NoSupportException("Resource does not support this interface!");
139 m_interfaces.push_back(interfaceType);
142 void SimulatorCollectionResourceImpl::removeInterface(const std::string &interfaceType)
144 if (m_interfaces.end() == std::find(m_interfaces.begin(), m_interfaces.end(), interfaceType))
146 SIM_LOG(ILogger::ERROR, "Resource does not support " << interfaceType << " interface currently!");
150 m_interfaces.erase(std::remove(m_interfaces.begin(), m_interfaces.end(), interfaceType), m_interfaces.end());
153 void SimulatorCollectionResourceImpl::addInterface(const std::vector<std::string> &interfaceList)
155 if (!interfaceList.size())
157 SIM_LOG(ILogger::ERROR, "Interface list is empty!");
161 for (auto interfaceType : interfaceList)
163 addInterface(interfaceType);
167 void SimulatorCollectionResourceImpl::removeInterface(const std::vector<std::string> &interfaceList)
169 if (!interfaceList.size())
171 SIM_LOG(ILogger::ERROR, "Interface list is empty!");
175 for (auto interfaceType : interfaceList)
177 removeInterface(interfaceType);
181 void SimulatorCollectionResourceImpl::setObservable(bool state)
183 std::lock_guard<std::recursive_mutex> lock(m_objectLock);
184 if (m_resourceHandle)
186 throw SimulatorException(SIMULATOR_OPERATION_NOT_ALLOWED,
187 "Observation state can not be changed when resource is started!");
191 m_property = static_cast<OCResourceProperty>(m_property | OC_OBSERVABLE);
193 m_property = static_cast<OCResourceProperty>(m_property ^ OC_OBSERVABLE);
196 void SimulatorCollectionResourceImpl::setObserverCallback(ObserverCallback callback)
198 VALIDATE_CALLBACK(callback)
199 m_observeCallback = callback;
202 void SimulatorCollectionResourceImpl::setModelChangeCallback(ResourceModelChangedCallback callback)
204 VALIDATE_CALLBACK(callback)
205 m_modelCallback = callback;
208 bool SimulatorCollectionResourceImpl::isObservable()
210 return (m_property & OC_OBSERVABLE);
213 bool SimulatorCollectionResourceImpl::isStarted()
215 return (nullptr != m_resourceHandle);
218 void SimulatorCollectionResourceImpl::start()
220 std::lock_guard<std::recursive_mutex> lock(m_objectLock);
221 if (m_resourceHandle)
223 throw SimulatorException(SIMULATOR_ERROR, "Collection already registered!");
226 if (m_uri.empty() || m_resourceType.empty())
228 throw SimulatorException(SIMULATOR_ERROR, "Found incomplete data to start resource!");
231 typedef OCStackResult (*RegisterResource)(OCResourceHandle &, std::string &, const std::string &,
232 const std::string &, OC::EntityHandler, uint8_t);
234 invokeocplatform(static_cast<RegisterResource>(OC::OCPlatform::registerResource),
235 m_resourceHandle, m_uri, m_resourceType, m_interfaces[0],
236 std::bind(&SimulatorCollectionResourceImpl::handleRequests,
237 this, std::placeholders::_1), m_property);
239 for (size_t index = 1; m_interfaces.size() > 1 && index < m_interfaces.size(); index++)
241 typedef OCStackResult (*bindInterfaceToResource)(const OCResourceHandle &,
242 const std::string &);
246 invokeocplatform(static_cast<bindInterfaceToResource>(
247 OC::OCPlatform::bindInterfaceToResource), m_resourceHandle,
248 m_interfaces[index]);
250 catch (SimulatorException &e)
258 void SimulatorCollectionResourceImpl::stop()
260 std::lock_guard<std::recursive_mutex> lock(m_objectLock);
261 if (!m_resourceHandle)
264 typedef OCStackResult (*UnregisterResource)(const OCResourceHandle &);
266 invokeocplatform(static_cast<UnregisterResource>(OC::OCPlatform::unregisterResource),
269 m_resourceHandle = nullptr;
272 SimulatorResourceModel SimulatorCollectionResourceImpl::getResourceModel()
274 std::lock_guard<std::mutex> lock(m_modelLock);
278 void SimulatorCollectionResourceImpl::setResourceModel(const SimulatorResourceModel &resModel)
280 std::lock_guard<std::mutex> lock(m_modelLock);
281 m_resModel = resModel;
284 void SimulatorCollectionResourceImpl::setActionType(std::map<RAML::ActionType, RAML::ActionPtr> &actionType)
286 m_actionTypes = actionType;
289 std::vector<ObserverInfo> SimulatorCollectionResourceImpl::getObserversList()
291 return m_observersList;
294 void SimulatorCollectionResourceImpl::notify(int id)
296 std::lock_guard<std::recursive_mutex> lock(m_objectLock);
297 if (!m_resourceHandle)
300 OC::ObservationIds observers {static_cast<OCObservationId>(id)};
301 sendNotification(observers);
304 void SimulatorCollectionResourceImpl::notifyAll()
306 std::lock_guard<std::recursive_mutex> lock(m_objectLock);
307 if (!m_resourceHandle)
310 if (!m_observersList.size())
313 OC::ObservationIds observers;
314 for (auto &observer : m_observersList)
315 observers.push_back(observer.id);
316 sendNotification(observers);
319 std::vector<std::string> SimulatorCollectionResourceImpl::getSupportedResources()
321 return m_supportedTypes;
324 void SimulatorCollectionResourceImpl::addChildResource(SimulatorResourceSP &resource)
326 VALIDATE_INPUT(!resource, "Invalid child resource!")
328 std::lock_guard<std::mutex> lock(m_childResourcesLock);
329 if (m_childResources.end() != m_childResources.find(resource->getURI()))
331 throw SimulatorException(SIMULATOR_ERROR, "Child resource with same URI is already exisit!");
334 m_childResources[resource->getURI()] = resource;
337 // Notify application and observers
339 m_modelCallback(m_uri, m_resModel);
343 void SimulatorCollectionResourceImpl::removeChildResource(SimulatorResourceSP &resource)
345 VALIDATE_INPUT(!resource, "Invalid child resource!")
347 std::lock_guard<std::mutex> lock(m_childResourcesLock);
348 if (m_childResources.end() == m_childResources.find(resource->getURI()))
350 throw SimulatorException(SIMULATOR_ERROR, "Child resource not found in collection!");
353 removeLink(resource->getURI());
354 m_childResources.erase(m_childResources.find(resource->getURI()));
356 // Notify application and observers
358 m_modelCallback(m_uri, m_resModel);
362 void SimulatorCollectionResourceImpl::removeChildResource(const std::string &uri)
364 VALIDATE_INPUT(uri.empty(), "Uri is empty!")
366 std::lock_guard<std::mutex> lock(m_childResourcesLock);
367 if (m_childResources.end() == m_childResources.find(uri))
369 throw SimulatorException(SIMULATOR_ERROR, "Child resource not found in collection!");
373 m_childResources.erase(m_childResources.find(uri));
375 // Notify application and observers
377 m_modelCallback(m_uri, m_resModel);
381 std::vector<SimulatorResourceSP> SimulatorCollectionResourceImpl::getChildResources()
383 std::lock_guard<std::mutex> lock(m_childResourcesLock);
385 std::vector<SimulatorResourceSP> result;
386 for (auto &entry : m_childResources)
387 result.push_back(entry.second);
392 OCEntityHandlerResult SimulatorCollectionResourceImpl::handleRequests(
393 std::shared_ptr<OC::OCResourceRequest> request)
398 if (OC::RequestHandlerFlag::RequestFlag & request->getRequestHandlerFlag())
401 OC::OCRepresentation rep = request->getResourceRepresentation();
402 std::string payload = getPayloadString(rep);
403 SIM_LOG(ILogger::INFO, "[" << m_name << "] " << request->getRequestType()
404 << " request received. \n**Payload details**\n" << payload)
407 // Handover the request to appropriate interface handler
408 std::string interfaceType(OC::DEFAULT_INTERFACE);
409 OC::QueryParamsMap queryParams = request->getQueryParameters();
410 if (queryParams.end() != queryParams.find("if"))
411 interfaceType = queryParams["if"];
413 std::shared_ptr<OC::OCResourceResponse> response;
414 if (interfaceType == OC::DEFAULT_INTERFACE)
416 response = requestOnBaseLineInterface(request);
418 else if (interfaceType == OC::LINK_INTERFACE)
420 response = requestOnLinkListInterface(request);
422 else if (interfaceType == OC::BATCH_INTERFACE)
424 response = requestOnBatchInterface(request);
427 // Send response if the request handled by resource
430 if (OC_STACK_OK != OC::OCPlatform::sendResponse(response))
435 SIM_LOG(ILogger::ERROR, "[" << m_name << "] " << "Unsupported request received!")
440 if (OC::RequestHandlerFlag::ObserverFlag & request->getRequestHandlerFlag())
444 SIM_LOG(ILogger::INFO, "[" << m_uri << "] OBSERVE request received")
445 SIM_LOG(ILogger::INFO, "[" << m_uri << "] Sending error as resource is in unobservable state!")
449 OC::ObservationInfo observationInfo = request->getObservationInfo();
450 if (OC::ObserveAction::ObserveRegister == observationInfo.action)
452 SIM_LOG(ILogger::INFO, "[" << m_uri << "] OBSERVE REGISTER request received");
454 ObserverInfo info {observationInfo.obsId, observationInfo.address, observationInfo.port};
455 m_observersList.push_back(info);
457 if (m_observeCallback)
458 m_observeCallback(m_uri, ObservationStatus::REGISTER, info);
460 else if (OC::ObserveAction::ObserveUnregister == observationInfo.action)
462 SIM_LOG(ILogger::INFO, "[" << m_uri << "] OBSERVE UNREGISTER request received");
465 for (auto iter = m_observersList.begin(); iter != m_observersList.end(); iter++)
467 if ((info = *iter), info.id == observationInfo.obsId)
469 m_observersList.erase(iter);
474 if (m_observeCallback)
475 m_observeCallback(m_uri, ObservationStatus::UNREGISTER, info);
482 std::shared_ptr<OC::OCResourceResponse> SimulatorCollectionResourceImpl::requestOnBaseLineInterface(
483 std::shared_ptr<OC::OCResourceRequest> request)
485 std::shared_ptr<OC::OCResourceResponse> response;
487 RAML::ActionType type = getActionType(request->getRequestType());
489 if (!m_actionTypes.empty())
491 if (m_actionTypes.end() == m_actionTypes.find(type))
495 if ("GET" == request->getRequestType())
497 // Construct the representation
498 OC::OCRepresentation ocRep = m_resModel.getOCRepresentation();
499 response = std::make_shared<OC::OCResourceResponse>();
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)
508 // TODO: Handle PUT, POST and DELETE requests
512 response->setRequestHandle(request->getRequestHandle());
513 response->setResourceHandle(request->getResourceHandle());
519 std::shared_ptr<OC::OCResourceResponse> SimulatorCollectionResourceImpl::requestOnLinkListInterface(
520 std::shared_ptr<OC::OCResourceRequest> request)
522 std::lock_guard<std::mutex> lock(m_childResourcesLock);
523 std::shared_ptr<OC::OCResourceResponse> response;
525 RAML::ActionType type = getActionType(request->getRequestType());
527 if (!m_actionTypes.empty())
529 if (m_actionTypes.end() == m_actionTypes.find(type))
533 if ("GET" == request->getRequestType())
535 // Construct the representation
536 OC::OCRepresentation ocRep;
537 std::vector<OC::OCRepresentation> links;
538 for (auto &entry : m_childResources)
540 OC::OCRepresentation oicLink;
541 oicLink.setValue("href", entry.second->getURI());
542 oicLink.setValue("rt", entry.second->getResourceType());
543 oicLink.setValue("if", entry.second->getInterface()[0]);
544 links.push_back(oicLink);
547 ocRep.setValue("links", links);
549 response = std::make_shared<OC::OCResourceResponse>();
550 response->setRequestHandle(request->getRequestHandle());
551 response->setResourceHandle(request->getResourceHandle());
552 response->setErrorCode(200);
553 response->setResponseResult(OC_EH_OK);
554 response->setResourceRepresentation(ocRep);
555 std::string resPayload = getPayloadString(ocRep);
556 SIM_LOG(ILogger::INFO, "[" << m_uri <<
557 "] Sending response for GET request. \n**Payload details**" << resPayload)
563 std::shared_ptr<OC::OCResourceResponse> SimulatorCollectionResourceImpl::requestOnBatchInterface(
564 std::shared_ptr<OC::OCResourceRequest>)
566 // TODO: Handle this interface
570 void SimulatorCollectionResourceImpl::sendNotification(OC::ObservationIds &observers)
572 std::lock_guard<std::recursive_mutex> lock(m_objectLock);
573 std::shared_ptr<OC::OCResourceResponse> response(new OC::OCResourceResponse());
574 response->setErrorCode(200);
575 response->setResponseResult(OC_EH_OK);
577 OC::OCRepresentation ocRep = m_resModel.getOCRepresentation();
578 response->setResourceRepresentation(ocRep, OC::DEFAULT_INTERFACE);
580 typedef OCStackResult (*NotifyListOfObservers)(OCResourceHandle, OC::ObservationIds &,
581 const std::shared_ptr<OC::OCResourceResponse>);
583 invokeocplatform(static_cast<NotifyListOfObservers>(OC::OCPlatform::notifyListOfObservers),
584 m_resourceHandle, observers, response);
587 void SimulatorCollectionResourceImpl::addLink(SimulatorResourceSP &resource)
589 std::lock_guard<std::mutex> lock(m_modelLock);
590 if (!m_resModel.containsAttribute("links"))
593 // Create new OIC Link
594 SimulatorResourceModel newLink;
595 newLink.add("href", resource->getURI());
596 newLink.add("rt", resource->getResourceType());
597 newLink.add("if", resource->getInterface()[0]);
599 // Add OIC Link if it is not present
601 std::vector<SimulatorResourceModel> links =
602 m_resModel.get<std::vector<SimulatorResourceModel>>("links");
603 for (auto &link : links)
605 std::string linkURI = link.get<std::string>("href");
606 if (linkURI == resource->getURI())
615 links.push_back(newLink);
616 m_resModel.updateValue("links", links);
620 void SimulatorCollectionResourceImpl::removeLink(std::string uri)
622 std::lock_guard<std::mutex> lock(m_modelLock);
623 if (!m_resModel.containsAttribute("links"))
626 // Add OIC Link if it is not present
627 std::vector<SimulatorResourceModel> links =
628 m_resModel.get<std::vector<SimulatorResourceModel>>("links");
629 for (size_t i = 0; i < links.size(); i++)
631 std::string linkURI = links[i].get<std::string>("href");
634 links.erase(links.begin() + i);
635 m_resModel.updateValue("links", links);
641 RAML::ActionType SimulatorCollectionResourceImpl::getActionType(std::string requestType)
643 if (!requestType.compare("GET"))
644 return RAML::ActionType::GET;
646 if (!requestType.compare("PUT"))
647 return RAML::ActionType::PUT;
649 if (!requestType.compare("POST"))
650 return RAML::ActionType::POST;
652 if (!requestType.compare("DELETE"))
653 return RAML::ActionType::DELETE;
655 return RAML::ActionType::NONE;