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);
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 m_interfaces = interfaces;
69 void SimulatorCollectionResourceImpl::setName(const std::string &name)
71 VALIDATE_INPUT(name.empty(), "Name is empty!")
73 std::lock_guard<std::recursive_mutex> lock(m_objectLock);
76 throw SimulatorException(SIMULATOR_OPERATION_NOT_ALLOWED,
77 "Name can not be set when collection is started!");
83 void SimulatorCollectionResourceImpl::setURI(const std::string &uri)
85 VALIDATE_INPUT(uri.empty(), "Uri is empty!")
87 std::lock_guard<std::recursive_mutex> lock(m_objectLock);
90 throw SimulatorException(SIMULATOR_OPERATION_NOT_ALLOWED,
91 "URI can not be set when collection is started!");
97 void SimulatorCollectionResourceImpl::setResourceType(const std::string &resourceType)
99 VALIDATE_INPUT(resourceType.empty(), "Resource type is empty!")
101 std::lock_guard<std::recursive_mutex> lock(m_objectLock);
102 if (m_resourceHandle)
104 throw SimulatorException(SIMULATOR_OPERATION_NOT_ALLOWED,
105 "Resource type can not be set when collection is started!");
108 m_resourceType = resourceType;
111 void SimulatorCollectionResourceImpl::addInterface(std::string interfaceType)
113 VALIDATE_INPUT(interfaceType.empty(), "Interface type is empty!")
115 if (interfaceType == OC::GROUP_INTERFACE)
117 throw NoSupportException("Collection resource does not support this interface type!");
120 std::lock_guard<std::recursive_mutex> lock(m_objectLock);
121 if (m_resourceHandle)
123 throw SimulatorException(SIMULATOR_OPERATION_NOT_ALLOWED,
124 "Interface type can not be set when resource is started!");
127 auto found = std::find(m_interfaces.begin(), m_interfaces.end(), interfaceType);
128 if (found != m_interfaces.end())
129 m_interfaces.push_back(interfaceType);
132 void SimulatorCollectionResourceImpl::setObservable(bool state)
134 std::lock_guard<std::recursive_mutex> lock(m_objectLock);
135 if (m_resourceHandle)
137 throw SimulatorException(SIMULATOR_OPERATION_NOT_ALLOWED,
138 "Observation state can not be changed when resource is started!");
142 m_property = static_cast<OCResourceProperty>(m_property | OC_OBSERVABLE);
144 m_property = static_cast<OCResourceProperty>(m_property ^ OC_OBSERVABLE);
147 void SimulatorCollectionResourceImpl::setObserverCallback(ObserverCallback callback)
149 VALIDATE_CALLBACK(callback)
150 m_observeCallback = callback;
153 void SimulatorCollectionResourceImpl::setModelChangeCallback(ResourceModelChangedCallback callback)
155 VALIDATE_CALLBACK(callback)
156 m_modelCallback = callback;
159 bool SimulatorCollectionResourceImpl::isObservable()
161 return (m_property & OC_OBSERVABLE);
164 bool SimulatorCollectionResourceImpl::isStarted()
166 return (nullptr != m_resourceHandle);
169 void SimulatorCollectionResourceImpl::start()
171 std::lock_guard<std::recursive_mutex> lock(m_objectLock);
172 if (m_resourceHandle)
174 throw SimulatorException(SIMULATOR_ERROR, "Collection already registered!");
177 if (m_uri.empty() || m_resourceType.empty())
179 throw SimulatorException(SIMULATOR_ERROR, "Found incomplete data to start resource!");
182 typedef OCStackResult (*RegisterResource)(OCResourceHandle &, std::string &, const std::string &,
183 const std::string &, OC::EntityHandler, uint8_t);
185 invokeocplatform(static_cast<RegisterResource>(OC::OCPlatform::registerResource),
186 m_resourceHandle, m_uri, m_resourceType, m_interfaces[0],
187 std::bind(&SimulatorCollectionResourceImpl::handleRequests,
188 this, std::placeholders::_1), m_property);
190 for (size_t index = 1; m_interfaces.size() > 1 && index < m_interfaces.size(); index++)
192 typedef OCStackResult (*bindInterfaceToResource)(const OCResourceHandle &,
193 const std::string &);
197 invokeocplatform(static_cast<bindInterfaceToResource>(
198 OC::OCPlatform::bindInterfaceToResource), m_resourceHandle,
199 m_interfaces[index]);
201 catch (SimulatorException &e)
209 void SimulatorCollectionResourceImpl::stop()
211 std::lock_guard<std::recursive_mutex> lock(m_objectLock);
212 if (!m_resourceHandle)
215 typedef OCStackResult (*UnregisterResource)(const OCResourceHandle &);
217 invokeocplatform(static_cast<UnregisterResource>(OC::OCPlatform::unregisterResource),
220 m_resourceHandle = nullptr;
223 SimulatorResourceModel SimulatorCollectionResourceImpl::getResourceModel()
225 std::lock_guard<std::mutex> lock(m_modelLock);
229 void SimulatorCollectionResourceImpl::setResourceModel(const SimulatorResourceModel &resModel)
231 std::lock_guard<std::mutex> lock(m_modelLock);
232 m_resModel = resModel;
235 void SimulatorCollectionResourceImpl::setActionType(std::map<RAML::ActionType, RAML::ActionPtr> &actionType)
237 m_actionTypes = actionType;
240 void SimulatorCollectionResourceImpl::setActionType(std::map<RAML::ActionType, RAML::ActionPtr> &actionType)
242 m_actionTypes = actionType;
245 std::vector<ObserverInfo> SimulatorCollectionResourceImpl::getObserversList()
247 return m_observersList;
250 void SimulatorCollectionResourceImpl::notify(int id)
252 std::lock_guard<std::recursive_mutex> lock(m_objectLock);
253 if (!m_resourceHandle)
256 OC::ObservationIds observers {static_cast<OCObservationId>(id)};
257 sendNotification(observers);
260 void SimulatorCollectionResourceImpl::notifyAll()
262 std::lock_guard<std::recursive_mutex> lock(m_objectLock);
263 if (!m_resourceHandle)
266 if (!m_observersList.size())
269 OC::ObservationIds observers;
270 for (auto &observer : m_observersList)
271 observers.push_back(observer.id);
272 sendNotification(observers);
275 std::vector<std::string> SimulatorCollectionResourceImpl::getSupportedResources()
277 return m_supportedTypes;
280 void SimulatorCollectionResourceImpl::addChildResource(SimulatorResourceSP &resource)
282 VALIDATE_INPUT(!resource, "Invalid child resource!")
284 std::lock_guard<std::mutex> lock(m_childResourcesLock);
285 if (m_childResources.end() != m_childResources.find(resource->getURI()))
287 throw SimulatorException(SIMULATOR_ERROR, "Child resource with same URI is already exisit!");
290 m_childResources[resource->getURI()] = resource;
293 // Notify application and observers
295 m_modelCallback(m_uri, m_resModel);
299 void SimulatorCollectionResourceImpl::removeChildResource(SimulatorResourceSP &resource)
301 VALIDATE_INPUT(!resource, "Invalid child resource!")
303 std::lock_guard<std::mutex> lock(m_childResourcesLock);
304 if (m_childResources.end() == m_childResources.find(resource->getURI()))
306 throw SimulatorException(SIMULATOR_ERROR, "Child resource not found in collection!");
309 removeLink(resource->getURI());
310 m_childResources.erase(m_childResources.find(resource->getURI()));
312 // Notify application and observers
314 m_modelCallback(m_uri, m_resModel);
318 void SimulatorCollectionResourceImpl::removeChildResource(const std::string &uri)
320 VALIDATE_INPUT(uri.empty(), "Uri is empty!")
322 std::lock_guard<std::mutex> lock(m_childResourcesLock);
323 if (m_childResources.end() == m_childResources.find(uri))
325 throw SimulatorException(SIMULATOR_ERROR, "Child resource not found in collection!");
329 m_childResources.erase(m_childResources.find(uri));
331 // Notify application and observers
333 m_modelCallback(m_uri, m_resModel);
337 std::vector<SimulatorResourceSP> SimulatorCollectionResourceImpl::getChildResources()
339 std::lock_guard<std::mutex> lock(m_childResourcesLock);
341 std::vector<SimulatorResourceSP> result;
342 for (auto &entry : m_childResources)
343 result.push_back(entry.second);
348 OCEntityHandlerResult SimulatorCollectionResourceImpl::handleRequests(
349 std::shared_ptr<OC::OCResourceRequest> request)
354 if (OC::RequestHandlerFlag::RequestFlag & request->getRequestHandlerFlag())
357 OC::OCRepresentation rep = request->getResourceRepresentation();
358 std::string payload = getPayloadString(rep);
359 SIM_LOG(ILogger::INFO, "[" << m_name << "] " << request->getRequestType()
360 << " request received. \n**Payload details**\n" << payload)
363 // Handover the request to appropriate interface handler
364 std::string interfaceType(OC::DEFAULT_INTERFACE);
365 OC::QueryParamsMap queryParams = request->getQueryParameters();
366 if (queryParams.end() != queryParams.find("if"))
367 interfaceType = queryParams["if"];
369 std::shared_ptr<OC::OCResourceResponse> response;
370 if (interfaceType == OC::DEFAULT_INTERFACE)
372 response = requestOnBaseLineInterface(request);
374 else if (interfaceType == OC::LINK_INTERFACE)
376 response = requestOnLinkListInterface(request);
378 else if (interfaceType == OC::BATCH_INTERFACE)
380 response = requestOnBatchInterface(request);
383 // Send response if the request handled by resource
386 if (OC_STACK_OK != OC::OCPlatform::sendResponse(response))
391 SIM_LOG(ILogger::ERROR, "[" << m_name << "] " << "Unsupported request received!")
396 if (OC::RequestHandlerFlag::ObserverFlag & request->getRequestHandlerFlag())
400 SIM_LOG(ILogger::INFO, "[" << m_uri << "] OBSERVE request received")
401 SIM_LOG(ILogger::INFO, "[" << m_uri << "] Sending error as resource is in unobservable state!")
405 OC::ObservationInfo observationInfo = request->getObservationInfo();
406 if (OC::ObserveAction::ObserveRegister == observationInfo.action)
408 SIM_LOG(ILogger::INFO, "[" << m_uri << "] OBSERVE REGISTER request received");
410 ObserverInfo info {observationInfo.obsId, observationInfo.address, observationInfo.port};
411 m_observersList.push_back(info);
413 if (m_observeCallback)
414 m_observeCallback(m_uri, ObservationStatus::REGISTER, info);
416 else if (OC::ObserveAction::ObserveUnregister == observationInfo.action)
418 SIM_LOG(ILogger::INFO, "[" << m_uri << "] OBSERVE UNREGISTER request received");
421 for (auto iter = m_observersList.begin(); iter != m_observersList.end(); iter++)
423 if ((info = *iter), info.id == observationInfo.obsId)
425 m_observersList.erase(iter);
430 if (m_observeCallback)
431 m_observeCallback(m_uri, ObservationStatus::UNREGISTER, info);
438 std::shared_ptr<OC::OCResourceResponse> SimulatorCollectionResourceImpl::requestOnBaseLineInterface(
439 std::shared_ptr<OC::OCResourceRequest> request)
441 std::shared_ptr<OC::OCResourceResponse> response;
443 RAML::ActionType type = getActionType(request->getRequestType());
445 if (!m_actionTypes.empty())
447 if (m_actionTypes.end() == m_actionTypes.find(type))
451 if ("GET" == request->getRequestType())
453 // Construct the representation
454 OC::OCRepresentation ocRep = m_resModel.getOCRepresentation();
455 response = std::make_shared<OC::OCResourceResponse>();
456 response->setErrorCode(200);
457 response->setResponseResult(OC_EH_OK);
458 response->setResourceRepresentation(ocRep);
459 std::string resPayload = getPayloadString(ocRep);
460 SIM_LOG(ILogger::INFO, "[" << m_uri <<
461 "] Sending response for GET request. \n**Payload details**" << resPayload)
464 // TODO: Handle PUT, POST and DELETE requests
468 response->setRequestHandle(request->getRequestHandle());
469 response->setResourceHandle(request->getResourceHandle());
475 std::shared_ptr<OC::OCResourceResponse> SimulatorCollectionResourceImpl::requestOnLinkListInterface(
476 std::shared_ptr<OC::OCResourceRequest> request)
478 std::lock_guard<std::mutex> lock(m_childResourcesLock);
479 std::shared_ptr<OC::OCResourceResponse> response;
481 RAML::ActionType type = getActionType(request->getRequestType());
483 if (!m_actionTypes.empty())
485 if (m_actionTypes.end() == m_actionTypes.find(type))
489 if ("GET" == request->getRequestType())
491 // Construct the representation
492 OC::OCRepresentation ocRep;
493 std::vector<OC::OCRepresentation> links;
494 for (auto &entry : m_childResources)
496 OC::OCRepresentation oicLink;
497 oicLink.setValue("href", entry.second->getURI());
498 oicLink.setValue("rt", entry.second->getResourceType());
499 oicLink.setValue("if", entry.second->getInterface()[0]);
500 links.push_back(oicLink);
503 ocRep.setValue("links", links);
505 response = std::make_shared<OC::OCResourceResponse>();
506 response->setRequestHandle(request->getRequestHandle());
507 response->setResourceHandle(request->getResourceHandle());
508 response->setErrorCode(200);
509 response->setResponseResult(OC_EH_OK);
510 response->setResourceRepresentation(ocRep);
511 std::string resPayload = getPayloadString(ocRep);
512 SIM_LOG(ILogger::INFO, "[" << m_uri <<
513 "] Sending response for GET request. \n**Payload details**" << resPayload)
519 std::shared_ptr<OC::OCResourceResponse> SimulatorCollectionResourceImpl::requestOnBatchInterface(
520 std::shared_ptr<OC::OCResourceRequest>)
522 // TODO: Handle this interface
526 void SimulatorCollectionResourceImpl::sendNotification(OC::ObservationIds &observers)
528 std::lock_guard<std::recursive_mutex> lock(m_objectLock);
529 std::shared_ptr<OC::OCResourceResponse> response(new OC::OCResourceResponse());
530 response->setErrorCode(200);
531 response->setResponseResult(OC_EH_OK);
533 OC::OCRepresentation ocRep = m_resModel.getOCRepresentation();
534 response->setResourceRepresentation(ocRep, OC::DEFAULT_INTERFACE);
536 typedef OCStackResult (*NotifyListOfObservers)(OCResourceHandle, OC::ObservationIds &,
537 const std::shared_ptr<OC::OCResourceResponse>);
539 invokeocplatform(static_cast<NotifyListOfObservers>(OC::OCPlatform::notifyListOfObservers),
540 m_resourceHandle, observers, response);
543 void SimulatorCollectionResourceImpl::addLink(SimulatorResourceSP &resource)
545 std::lock_guard<std::mutex> lock(m_modelLock);
546 if (!m_resModel.containsAttribute("links"))
549 // Create new OIC Link
550 SimulatorResourceModel newLink;
551 newLink.add("href", resource->getURI());
552 newLink.add("rt", resource->getResourceType());
553 newLink.add("if", resource->getInterface()[0]);
555 // Add OIC Link if it is not present
557 std::vector<SimulatorResourceModel> links =
558 m_resModel.get<std::vector<SimulatorResourceModel>>("links");
559 for (auto &link : links)
561 std::string linkURI = link.get<std::string>("href");
562 if (linkURI == resource->getURI())
571 links.push_back(newLink);
572 m_resModel.updateValue("links", links);
576 void SimulatorCollectionResourceImpl::removeLink(std::string uri)
578 std::lock_guard<std::mutex> lock(m_modelLock);
579 if (!m_resModel.containsAttribute("links"))
582 // Add OIC Link if it is not present
583 std::vector<SimulatorResourceModel> links =
584 m_resModel.get<std::vector<SimulatorResourceModel>>("links");
585 for (size_t i = 0; i < links.size(); i++)
587 std::string linkURI = links[i].get<std::string>("href");
590 links.erase(links.begin() + i);
591 m_resModel.updateValue("links", links);
597 RAML::ActionType SimulatorCollectionResourceImpl::getActionType(std::string requestType)
599 if (!requestType.compare("GET"))
600 return RAML::ActionType::GET;
602 if (!requestType.compare("PUT"))
603 return RAML::ActionType::PUT;
605 if (!requestType.compare("POST"))
606 return RAML::ActionType::POST;
608 if (!requestType.compare("DELETE"))
609 return RAML::ActionType::DELETE;
611 return RAML::ActionType::NONE;