Updated control logic of Scene Resource.
[platform/upstream/iotivity.git] / service / scene-manager / src / SceneCollectionResource.cpp
1 //******************************************************************
2 //
3 // Copyright 2016 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 "SceneCollectionResource.h"
22
23 #include <atomic>
24 #include "OCApi.h"
25 #include "RCSRequest.h"
26 #include "RCSSeparateResponse.h"
27
28 namespace OIC
29 {
30     namespace Service
31     {
32         namespace
33         {
34             std::atomic_int numOfSceneCollection(0);
35         }
36
37         SceneCollectionResource::Ptr
38         SceneCollectionResource::createSceneCollectionObject()
39         {
40             SceneCollectionResource::Ptr newSceneCollectionObject(new SceneCollectionResource());
41
42             newSceneCollectionObject->m_uri
43                 = PREFIX_SCENE_COLLECTION_URI + "/" + std::to_string(numOfSceneCollection++);
44
45             newSceneCollectionObject->m_address = SceneUtils::getNetAddress();
46
47             newSceneCollectionObject->createResourceObject();
48
49             newSceneCollectionObject->setDefaultAttributes();
50
51             newSceneCollectionObject->initSetRequestHandler();
52
53             return newSceneCollectionObject;
54         }
55
56         void SceneCollectionResource::createResourceObject()
57         {
58             m_sceneCollectionResourceObj
59                 = RCSResourceObject::Builder(
60                         m_uri, SCENE_COLLECTION_RT, OC_RSRVD_INTERFACE_DEFAULT).
61                         addInterface(OC::BATCH_INTERFACE).
62                         setDiscoverable(true).setObservable(false).build();
63         }
64
65         void SceneCollectionResource::setDefaultAttributes()
66         {
67             m_sceneCollectionResourceObj->setAttribute(SCENE_KEY_LAST_SCENE, std::string());
68             m_sceneCollectionResourceObj->setAttribute(SCENE_KEY_NAME, std::string());
69             m_sceneCollectionResourceObj->setAttribute(
70                     SCENE_KEY_ID, SceneUtils::OICGenerateUUIDStr());
71             m_sceneCollectionResourceObj->setAttribute(SCENE_KEY_RTS, SCENE_MEMBER_RT);
72             m_sceneCollectionResourceObj->setAttribute(
73                     SCENE_KEY_SCENEVALUES, std::vector<std::string>());
74             m_sceneCollectionResourceObj->setAttribute(SCENE_KEY_URI, m_uri);
75         }
76
77         void SceneCollectionResource::initSetRequestHandler()
78         {
79             m_requestHandler.m_owner
80                 = std::weak_ptr<SceneCollectionResource>(shared_from_this());
81
82             m_sceneCollectionResourceObj->setSetRequestHandler(std::bind(
83                     &SceneCollectionResource::SceneCollectionRequestHandler::onSetRequest,
84                     m_requestHandler, std::placeholders::_1, std::placeholders::_2));
85         }
86
87         void SceneCollectionResource::addScene(const std::string & newScene)
88         {
89             addScene(std::string(newScene));
90         }
91
92         void SceneCollectionResource::addScene(std::string && newScene)
93         {
94             auto sceneValues = m_sceneCollectionResourceObj->getAttributeValue(
95                     SCENE_KEY_SCENEVALUES).get< std::vector< std::string > >();
96
97             auto foundScene
98                 = std::find(sceneValues.begin(), sceneValues.end(), newScene);
99             if (foundScene == sceneValues.end())
100             {
101                 sceneValues.push_back(std::move(newScene));
102
103                 m_sceneCollectionResourceObj->setAttribute(SCENE_KEY_SCENEVALUES, sceneValues);
104             }
105         }
106
107         void SceneCollectionResource::addSceneMember(
108                 SceneMemberResource::Ptr newMember)
109         {
110             std::lock_guard<std::mutex> memberlock(m_sceneMemberLock);
111
112             auto foundmember = std::find_if(m_sceneMembers.begin(), m_sceneMembers.end(),
113                     [& newMember](const SceneMemberResource::Ptr & ptr) -> bool
114                     {
115                         return ptr->getFullUri() == newMember->getFullUri();
116                     });
117
118             if (foundmember != m_sceneMembers.end())
119             {
120                 throw std::exception();
121             }
122
123             m_sceneMembers.push_back(newMember);
124             m_sceneCollectionResourceObj->bindResource(newMember->getRCSResourceObject());
125         }
126
127         void SceneCollectionResource::execute(std::string && sceneName)
128         {
129             execute(std::move(sceneName), nullptr);
130         }
131
132         void SceneCollectionResource::execute(const std::string & sceneName)
133         {
134             execute(std::string(sceneName));
135         }
136
137         void SceneCollectionResource::execute(
138                 const std::string & sceneName, SceneExecuteCallback executeCB)
139         {
140             execute(std::string(sceneName), std::move(executeCB));
141         }
142
143         void SceneCollectionResource::execute(
144                 std::string && sceneName, SceneExecuteCallback executeCB)
145         {
146             auto sceneValues = m_sceneCollectionResourceObj->getAttributeValue(
147                     SCENE_KEY_SCENEVALUES).get< std::vector< std::string > >();
148
149             auto foundSceneValue
150                 = std::find(sceneValues.begin(), sceneValues.end(), sceneName);
151             if (foundSceneValue == sceneValues.end() && executeCB)
152             {
153                 std::thread(executeCB, SCENE_CLIENT_BADREQUEST).detach();
154                 return;
155             }
156
157             auto executeHandler
158                 = SceneExecuteResponseHandler::createExecuteHandler(
159                         shared_from_this(), std::move(executeCB));
160
161             {
162                 std::lock_guard<std::mutex> handlerlock(m_executeHandlerLock);
163                 m_executeHandlers.push_back(executeHandler);
164             }
165
166             {
167                 std::lock_guard<std::mutex> memberlock(m_sceneMemberLock);
168                 for (auto & it : m_sceneMembers)
169                 {
170                     it->execute(sceneName, std::bind(
171                             &SceneExecuteResponseHandler::onResponse, executeHandler,
172                             std::placeholders::_1, std::placeholders::_2));
173                 }
174             }
175
176             m_sceneCollectionResourceObj->setAttribute(SCENE_KEY_LAST_SCENE, sceneName);
177         }
178
179         void SceneCollectionResource::onExecute(
180                 int errorCode, SceneExecuteCallback cb, SceneExecuteResponseHandler::Ptr ptr)
181         {
182             {
183                 std::lock_guard<std::mutex> handlerlock(m_executeHandlerLock);
184                 m_executeHandlers.remove(ptr);
185             }
186
187             std::thread(cb, errorCode).detach();
188         }
189
190         std::string SceneCollectionResource::getId() const
191         {
192             return m_sceneCollectionResourceObj->getAttributeValue(
193                     SCENE_KEY_ID).get<std::string>();
194         }
195
196         std::string SceneCollectionResource::getUri() const
197         {
198             return m_uri;
199         }
200
201         std::string SceneCollectionResource::getAddress() const
202         {
203             return m_address;
204         }
205
206         std::vector<std::string> SceneCollectionResource::getSceneValues() const
207         {
208             return m_sceneCollectionResourceObj->getAttributeValue(
209                     SCENE_KEY_SCENEVALUES).get<std::vector<std::string>>();
210         }
211
212         std::vector<SceneMemberResource::Ptr> SceneCollectionResource::getSceneMembers() const
213         {
214             return m_sceneMembers;
215         }
216
217         RCSResourceObject::Ptr SceneCollectionResource::getRCSResourceObject() const
218         {
219             return m_sceneCollectionResourceObj;
220         }
221
222         void SceneCollectionResource::setName(std::string && sceneCollectionName)
223         {
224             m_sceneCollectionResourceObj->setAttribute(
225                     SCENE_KEY_NAME, std::move(sceneCollectionName));
226         }
227
228         void SceneCollectionResource::setName(const std::string & sceneCollectionName)
229         {
230             setName(std::string(sceneCollectionName));
231         }
232
233         std::string SceneCollectionResource::getName() const
234         {
235             return m_sceneCollectionResourceObj->getAttributeValue(
236                     SCENE_KEY_NAME).get<std::string>();
237         }
238
239         RCSSetResponse SceneCollectionResource::SceneCollectionRequestHandler::
240         onSetRequest(const RCSRequest & request, RCSResourceAttributes & attributes)
241         {
242             if (request.getInterface() == OC::BATCH_INTERFACE)
243             {
244                 return createSceneMemberRequest(request, attributes);
245             }
246
247             if (attributes.contains(SCENE_KEY_SCENEVALUES))
248             {
249                 return addSceneRequest(request, attributes);
250             }
251
252             if (attributes.contains(SCENE_KEY_LAST_SCENE))
253             {
254                 return executeSceneRequest(request, attributes);
255             }
256
257             if (attributes.contains(SCENE_KEY_NAME))
258             {
259                 return setSceneCollectionName(request, attributes);
260             }
261
262             return RCSSetResponse::create(attributes, (int)SCENE_CLIENT_BADREQUEST).
263                     setAcceptanceMethod(RCSSetResponse::AcceptanceMethod::IGNORE);
264         }
265
266         RCSSetResponse SceneCollectionResource::SceneCollectionRequestHandler::
267         addSceneRequest(const RCSRequest & /*request*/, RCSResourceAttributes & attributes)
268         {
269             SceneCollectionResource::Ptr ptr = m_owner.lock();
270             if (ptr == nullptr)
271             {
272                 return RCSSetResponse::create(attributes, SCENE_CLIENT_BADREQUEST).
273                         setAcceptanceMethod(RCSSetResponse::AcceptanceMethod::IGNORE);
274             }
275
276             auto values = attributes.at(SCENE_KEY_SCENEVALUES).get<std::vector<std::string>>();
277             std::for_each (values.begin(), values.end(),
278                     [& ptr](const std::string & value)
279                     {
280                         ptr->addScene(value);
281                     });
282
283             return RCSSetResponse::create(attributes).
284                     setAcceptanceMethod(RCSSetResponse::AcceptanceMethod::IGNORE);
285         }
286
287         RCSSetResponse SceneCollectionResource::SceneCollectionRequestHandler::
288         executeSceneRequest(const RCSRequest & request, RCSResourceAttributes & attributes)
289         {
290             SceneCollectionResource::Ptr ptr = m_owner.lock();
291             if (ptr == nullptr)
292             {
293                 return RCSSetResponse::create(attributes, SCENE_CLIENT_BADREQUEST).
294                         setAcceptanceMethod(RCSSetResponse::AcceptanceMethod::IGNORE);
295             }
296
297             auto requestKey = attributes.at(SCENE_KEY_LAST_SCENE).get<std::string>();
298
299             RCSRequest req(request.getResourceObject().lock(), request.getOCRequest());
300             ptr->execute(std::string(requestKey), std::bind(
301                     &SceneCollectionResource::SceneCollectionRequestHandler::onExecute, this,
302                     std::placeholders::_1, req, attributes));
303
304             return RCSSetResponse::separate();
305         }
306
307         RCSSetResponse SceneCollectionResource::SceneCollectionRequestHandler::
308         createSceneMemberRequest(const RCSRequest & /*request*/, RCSResourceAttributes & attributes)
309         {
310             SceneCollectionResource::Ptr ptr = m_owner.lock();
311             if (ptr == nullptr || !attributes.contains(SCENE_KEY_PAYLOAD_LINK))
312             {
313                 return RCSSetResponse::create(attributes, SCENE_CLIENT_BADREQUEST).
314                         setAcceptanceMethod(RCSSetResponse::AcceptanceMethod::IGNORE);
315             }
316
317             auto linkAtt = attributes.at(SCENE_KEY_PAYLOAD_LINK).get<RCSResourceAttributes>();
318             if (!linkAtt.contains(SCENE_KEY_HREF) ||
319                     !linkAtt.contains(SCENE_KEY_RT) || !linkAtt.contains(SCENE_KEY_IF))
320             {
321                 return RCSSetResponse::create(attributes, SCENE_CLIENT_BADREQUEST).
322                         setAcceptanceMethod(RCSSetResponse::AcceptanceMethod::IGNORE);
323             }
324
325             auto memberObj = createSceneMemberFromRemote(linkAtt);
326             if (memberObj == nullptr)
327             {
328                 return RCSSetResponse::create(attributes, SCENE_CLIENT_BADREQUEST).
329                         setAcceptanceMethod(RCSSetResponse::AcceptanceMethod::IGNORE);
330             }
331
332             if (attributes.contains(SCENE_KEY_SCENEMAPPINGS))
333             {
334                 addMemberInfoFromRemote(memberObj, attributes.at(
335                         SCENE_KEY_SCENEMAPPINGS).get<std::vector<RCSResourceAttributes>>());
336             }
337
338             RCSResourceAttributes responseAtt(attributes);
339             responseAtt[SCENE_KEY_ID] = RCSResourceAttributes::Value(memberObj->getId());
340             responseAtt[SCENE_KEY_CREATEDLINK]
341                         = RCSResourceAttributes::Value(memberObj->getFullUri());
342
343             return RCSSetResponse::create(responseAtt).
344                     setAcceptanceMethod(RCSSetResponse::AcceptanceMethod::IGNORE);
345         }
346
347         RCSSetResponse
348         SceneCollectionResource::SceneCollectionRequestHandler::setSceneCollectionName(
349                 const RCSRequest & /*request*/, RCSResourceAttributes & attr)
350         {
351             SceneCollectionResource::Ptr ptr = m_owner.lock();
352             if (ptr == nullptr)
353             {
354                 return RCSSetResponse::create(attr, SCENE_CLIENT_BADREQUEST).
355                         setAcceptanceMethod(RCSSetResponse::AcceptanceMethod::IGNORE);
356             }
357
358             ptr->setName(attr.at(SCENE_KEY_NAME).get<std::string>());
359
360             return RCSSetResponse::create(attr).
361                     setAcceptanceMethod(RCSSetResponse::AcceptanceMethod::IGNORE);
362         }
363
364         SceneMemberResource::Ptr
365         SceneCollectionResource::SceneCollectionRequestHandler::createSceneMemberFromRemote(
366                 RCSResourceAttributes & linkAtt)
367         {
368             auto memberObj = SceneMemberResource::createSceneMemberResource(linkAtt);
369
370             try
371             {
372                 SceneCollectionResource::Ptr ptr = m_owner.lock();
373                 ptr->addSceneMember(memberObj);
374             } catch (...)
375             {
376                 return nullptr;
377             }
378
379             return memberObj;
380         }
381
382         void SceneCollectionResource::SceneCollectionRequestHandler::addMemberInfoFromRemote(
383                 SceneMemberResource::Ptr memberObj, std::vector<RCSResourceAttributes> mInfo)
384         {
385             std::for_each (mInfo.begin(), mInfo.end(),
386                     [& memberObj](const RCSResourceAttributes & att)
387                     {
388                         memberObj->addMappingInfo(SceneMemberResource::MappingInfo(
389                                 att.at(SCENE_KEY_SCENE).get<std::string>(),
390                                 att.at(SCENE_KEY_MEMBERPROPERTY).get<std::string>(),
391                                 att.at(SCENE_KEY_MEMBERVALUE)));
392                     });
393         }
394
395         void SceneCollectionResource::SceneCollectionRequestHandler::
396         onExecute(int /*errorCode*/, const RCSRequest & request, RCSResourceAttributes & /*att*/)
397         {
398             // TODO need to set error code.
399             // and need to set specific attr' but this attr not to be apply to RCSResourceObject.
400             RCSSeparateResponse(request).set();
401         }
402
403         void SceneCollectionResource::SceneExecuteResponseHandler::
404         onResponse(const RCSResourceAttributes & /*attributes*/, int errorCode)
405         {
406             m_responseMembers++;
407             if (errorCode != SCENE_RESPONSE_SUCCESS && m_errorCode != errorCode)
408             {
409                 m_errorCode = errorCode;
410             }
411             if (m_responseMembers == m_numOfMembers)
412             {
413                 m_cb(m_errorCode);
414             }
415         }
416
417         SceneCollectionResource::SceneExecuteResponseHandler::Ptr
418         SceneCollectionResource::SceneExecuteResponseHandler::createExecuteHandler(
419                 const SceneCollectionResource::Ptr ptr, SceneExecuteCallback executeCB)
420         {
421             auto executeHandler = std::make_shared<SceneExecuteResponseHandler>();
422
423             executeHandler->m_numOfMembers = ptr->m_sceneMembers.size();
424             executeHandler->m_responseMembers = 0;
425
426             executeHandler->m_cb = std::bind(
427                     &SceneCollectionResource::onExecute, ptr,
428                     std::placeholders::_1, std::move(executeCB), executeHandler);
429
430             executeHandler->m_owner
431                 = std::weak_ptr<SceneCollectionResource>(ptr);
432             executeHandler->m_errorCode  = SCENE_RESPONSE_SUCCESS;
433
434             return executeHandler;
435         }
436     }
437 }
438