Merge branch 'master' into group-manager
[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
27 namespace OIC
28 {
29     namespace Service
30     {
31         namespace
32         {
33             std::atomic_int numOfSceneCollection(0);
34         }
35
36         SceneCollectionResource::Ptr
37         SceneCollectionResource::createSceneCollectionObject()
38         {
39             auto instance = new SceneCollectionResource();
40             SceneCollectionResource::Ptr newSceneCollectionObject;
41             newSceneCollectionObject.reset(instance);
42
43             newSceneCollectionObject->m_Uri
44                 = PREFIX_SCENE_COLLECTION_URI + "/" + std::to_string(numOfSceneCollection++);
45
46             newSceneCollectionObject->m_SceneCollectionResourceObj
47                 = RCSResourceObject::Builder(
48                         newSceneCollectionObject->m_Uri,
49                         SCENE_COLLECTION_RT, OC_RSRVD_INTERFACE_DEFAULT).
50                         addInterface(OC::BATCH_INTERFACE).
51                         setDiscoverable(true).setObservable(false).build();
52
53             auto collectionObj = newSceneCollectionObject->m_SceneCollectionResourceObj;
54             {
55                 RCSResourceObject::LockGuard guard(collectionObj);
56                 collectionObj->setAttribute(SCENE_KEY_LAST_SCENE, std::string());
57                 collectionObj->setAttribute(SCENE_KEY_NAME, std::string());
58                 collectionObj->setAttribute(SCENE_KEY_ID, SceneUtils::OICGenerateUUIDStr());
59                 collectionObj->setAttribute(SCENE_KEY_RTS, SCENE_MEMBER_RT);
60                 collectionObj->setAttribute(SCENE_KEY_SCENEVALUES, std::vector<std::string>());
61             }
62
63             newSceneCollectionObject->m_RequestHandler.m_Owner
64                 = std::weak_ptr<SceneCollectionResource>(newSceneCollectionObject);
65
66             collectionObj->setSetRequestHandler(std::bind(
67                     &SceneCollectionResource::SceneCollectionRequestHandler::onSetRequest,
68                     newSceneCollectionObject->m_RequestHandler,
69                     std::placeholders::_1, std::placeholders::_2));
70
71             newSceneCollectionObject->m_Address = SceneUtils::getNetAddress();
72
73             return newSceneCollectionObject;
74         }
75
76         void SceneCollectionResource::addScene(const std::string & newScene)
77         {
78             addScene(std::string(newScene));
79         }
80
81         void SceneCollectionResource::addScene(std::string && newScene)
82         {
83             auto sceneValues = m_SceneCollectionResourceObj->getAttributeValue(
84                     SCENE_KEY_SCENEVALUES).get< std::vector< std::string > >();
85
86             auto foundScene
87                 = std::find(sceneValues.begin(), sceneValues.end(), newScene);
88             if (foundScene == sceneValues.end())
89             {
90                 sceneValues.push_back(std::move(newScene));
91
92                 RCSResourceObject::LockGuard guard(m_SceneCollectionResourceObj);
93                 m_SceneCollectionResourceObj->setAttribute(
94                         SCENE_KEY_SCENEVALUES, sceneValues);
95             }
96         }
97
98         void SceneCollectionResource::addSceneMember(
99                 SceneMemberResource::Ptr newMember)
100         {
101             std::unique_lock<std::mutex> memberlock(m_SceneMemberLock);
102
103             struct FindMember
104             {
105                 bool operator()(SceneMemberResource::Ptr ptr) const
106                 {
107                     return ptr->getFullUri() == name;
108                 }
109                 std::string name;
110             };
111             FindMember fMember;
112             fMember.name = newMember->getFullUri();
113             auto foundmember = std::find_if(
114                     m_SceneMembers.begin(), m_SceneMembers.end(), fMember);
115             if (foundmember != m_SceneMembers.end())
116             {
117                 // TODO will change to Scene Exception.
118                 throw std::exception();
119             }
120
121             m_SceneMembers.push_back(newMember);
122             m_SceneCollectionResourceObj->bindResource(newMember->getRCSResourceObject());
123         }
124
125         void SceneCollectionResource::execute(std::string && sceneName)
126         {
127             execute(std::move(sceneName), nullptr);
128         }
129
130         void SceneCollectionResource::execute(const std::string & sceneName)
131         {
132             execute(std::string(sceneName));
133         }
134
135         void SceneCollectionResource::execute(
136                 const std::string & sceneName, SceneExecuteCallback executeCB)
137         {
138             execute(std::string(sceneName), std::move(executeCB));
139         }
140
141         void SceneCollectionResource::execute(
142                 std::string && sceneName, SceneExecuteCallback executeCB)
143         {
144             auto sceneValues = m_SceneCollectionResourceObj->getAttributeValue(
145                     SCENE_KEY_SCENEVALUES).get< std::vector< std::string > >();
146             auto foundSceneValue
147                 = std::find(sceneValues.begin(), sceneValues.end(), sceneName);
148
149             if (foundSceneValue == sceneValues.end())
150             {
151                 if (executeCB)
152                 {
153                     executeCB(SCENE_CLIENT_BADREQUEST);
154                 }
155                 return;
156             }
157
158             auto executeHandler
159                 = SceneExecuteResponseHandler::createExecuteHandler(
160                         shared_from_this(), std::move(executeCB));
161
162             std::unique_lock<std::mutex> handlerlock(m_ExecuteHandlerLock);
163             m_ExecuteHandlers.push_back(executeHandler);
164             handlerlock.unlock();
165
166             std::unique_lock<std::mutex> memberlock(m_SceneMemberLock);
167             for (unsigned int it = 0; it < m_SceneMembers.size(); ++it)
168             {
169                 m_SceneMembers[it]->execute(sceneName, std::bind(
170                         &SceneExecuteResponseHandler::onResponse, executeHandler,
171                         std::placeholders::_1, std::placeholders::_2));
172             }
173             memberlock.unlock();
174
175             RCSResourceObject::LockGuard guard(m_SceneCollectionResourceObj);
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             std::unique_lock<std::mutex> handlerlock(m_ExecuteHandlerLock);
183             m_ExecuteHandlers.remove(ptr);
184             handlerlock.unlock();
185
186             cb(errorCode);
187         }
188
189         std::string SceneCollectionResource::getId() const
190         {
191             return m_SceneCollectionResourceObj->
192                     getAttributeValue(SCENE_KEY_ID).get<std::string>();
193         }
194
195         std::string SceneCollectionResource::getUri() const
196         {
197             return m_Uri;
198         }
199
200         std::string SceneCollectionResource::getAddress() const
201         {
202             return m_Address;
203         }
204
205         const std::vector<SceneMemberResource::Ptr>
206         SceneCollectionResource::getSceneMembers()
207         {
208             std::unique_lock<std::mutex> memberlock(m_SceneMemberLock);
209             std::vector<SceneMemberResource::Ptr> retMembers(m_SceneMembers);
210             return retMembers;
211         }
212
213         RCSResourceObject::Ptr SceneCollectionResource::getRCSResourceObject() const
214         {
215             return m_SceneCollectionResourceObj;
216         }
217
218         void SceneCollectionResource::setName(std::string && sceneCollectionName)
219         {
220             RCSResourceObject::LockGuard guard(m_SceneCollectionResourceObj);
221             m_SceneCollectionResourceObj->setAttribute(
222                     SCENE_KEY_NAME, std::move(sceneCollectionName));
223         }
224
225         void SceneCollectionResource::setName(const std::string & sceneCollectionName)
226         {
227             setName(std::string(sceneCollectionName));
228         }
229
230         std::string SceneCollectionResource::getName() const
231         {
232             return m_SceneCollectionResourceObj->getAttributeValue(
233                     SCENE_KEY_NAME).get<std::string>();
234         }
235
236         RCSSetResponse SceneCollectionResource::SceneCollectionRequestHandler::
237         onSetRequest(const RCSRequest & request, RCSResourceAttributes & attributes)
238         {
239             if (request.getInterface() == OC::BATCH_INTERFACE)
240             {
241                 return createSceneMemberRequest(request, attributes);
242             }
243
244             if (attributes.contains(SCENE_KEY_SCENEVALUES))
245             {
246                 return addSceneRequest(request, attributes);
247             }
248
249             if (attributes.contains(SCENE_KEY_LAST_SCENE))
250             {
251                 return executeSceneRequest(request, attributes);
252             }
253
254             return RCSSetResponse::create(attributes, (int)SCENE_CLIENT_BADREQUEST)
255             .setAcceptanceMethod(RCSSetResponse::AcceptanceMethod::IGNORE);
256         }
257
258         RCSSetResponse SceneCollectionResource::SceneCollectionRequestHandler::
259         addSceneRequest(const RCSRequest & /*request*/, RCSResourceAttributes & attributes)
260         {
261             SceneCollectionResource::Ptr ptr = m_Owner.lock();
262             if (ptr == nullptr)
263             {
264                 return RCSSetResponse::create(
265                         RCSResourceAttributes(attributes), SCENE_CLIENT_BADREQUEST).
266                         setAcceptanceMethod(RCSSetResponse::AcceptanceMethod::IGNORE);
267             }
268
269             auto scenes = attributes.at(SCENE_KEY_SCENEVALUES).get<std::vector<std::string>>();
270
271             for(unsigned int it = 0; it < scenes.size(); ++it)
272             {
273                 ptr->addScene(scenes[it]);
274             }
275
276             return RCSSetResponse::create(RCSResourceAttributes(attributes)).
277                     setAcceptanceMethod(RCSSetResponse::AcceptanceMethod::IGNORE);
278         }
279
280         RCSSetResponse SceneCollectionResource::SceneCollectionRequestHandler::
281         executeSceneRequest(const RCSRequest & /*request*/, RCSResourceAttributes & attributes)
282         {
283             SceneCollectionResource::Ptr ptr = m_Owner.lock();
284             if (ptr == nullptr)
285             {
286                 return RCSSetResponse::create(
287                         RCSResourceAttributes(attributes), SCENE_CLIENT_BADREQUEST).
288                         setAcceptanceMethod(RCSSetResponse::AcceptanceMethod::IGNORE);
289             }
290
291             auto request_key = attributes.at(SCENE_KEY_LAST_SCENE).get<std::string>();
292             ptr->execute(std::string(request_key), std::bind(
293                     &SceneCollectionResource::SceneCollectionRequestHandler::onExecute, this,
294                     std::placeholders::_1,
295                     attributes));
296
297             // TODO slow response
298             return RCSSetResponse::create(RCSResourceAttributes(attributes))
299             .setAcceptanceMethod(RCSSetResponse::AcceptanceMethod::IGNORE);
300         }
301
302         RCSSetResponse SceneCollectionResource::SceneCollectionRequestHandler::
303         createSceneMemberRequest(const RCSRequest & /*request*/, RCSResourceAttributes & attributes)
304         {
305             SceneCollectionResource::Ptr ptr = m_Owner.lock();
306             if (ptr == nullptr || !attributes.contains(SCENE_KEY_PAYLOAD_LINK))
307             {
308                 return RCSSetResponse::create(
309                         RCSResourceAttributes(attributes), SCENE_CLIENT_BADREQUEST).
310                         setAcceptanceMethod(RCSSetResponse::AcceptanceMethod::IGNORE);
311             }
312
313             auto linkAtt = attributes.at(SCENE_KEY_PAYLOAD_LINK).get<RCSResourceAttributes>();
314
315             auto memberObj
316                 = SceneMemberResource::createSceneMemberResource(linkAtt);
317
318             try
319             {
320                 ptr->addSceneMember(memberObj);
321             } catch (...)
322             {
323                 memberObj.reset();
324                 return RCSSetResponse::create(
325                         RCSResourceAttributes(attributes), SCENE_CLIENT_BADREQUEST).
326                         setAcceptanceMethod(RCSSetResponse::AcceptanceMethod::IGNORE);
327             }
328
329             if (attributes.contains(SCENE_KEY_SCENEMAPPINGS))
330             {
331                 auto sceneMappings
332                     = attributes.at(SCENE_KEY_SCENEMAPPINGS).get<std::vector<RCSResourceAttributes>>();
333                 for (unsigned int it = 0; it < sceneMappings.size(); ++it)
334                 {
335                     memberObj->addMappingInfo(SceneMemberResource::MappingInfo(
336                             sceneMappings[it].at(SCENE_KEY_SCENE).get<std::string>(),
337                             sceneMappings[it].at(SCENE_KEY_MEMBERPROPERTY).get<std::string>(),
338                             sceneMappings[it].at(SCENE_KEY_MEMBERVALUE)));
339                 }
340             }
341
342             RCSResourceAttributes responseAtt(attributes);
343             responseAtt[SCENE_KEY_ID] = RCSResourceAttributes::Value(memberObj->getId());
344             responseAtt[SCENE_KEY_CREATEDLINK]
345                         = RCSResourceAttributes::Value(memberObj->getFullUri());
346
347             return RCSSetResponse::create(responseAtt)
348             .setAcceptanceMethod(RCSSetResponse::AcceptanceMethod::IGNORE);
349         }
350
351         void SceneCollectionResource::SceneCollectionRequestHandler::
352         onExecute(int /*errorCode*/, /*const RCSRequest & request,*/ RCSResourceAttributes & /*att*/)
353         {
354             // TODO slow response
355         }
356
357         void SceneCollectionResource::SceneExecuteResponseHandler::
358         onResponse(const RCSResourceAttributes & /*attributes*/, int errorCode)
359         {
360             m_responseMembers++;
361             if (errorCode != SCENE_RESPONSE_SUCCESS && m_errorCode != errorCode)
362             {
363                 m_errorCode = errorCode;
364             }
365             if (m_responseMembers == m_numOfMembers)
366             {
367                 m_Cb(m_errorCode);
368             }
369         }
370
371         SceneCollectionResource::SceneExecuteResponseHandler::Ptr
372         SceneCollectionResource::SceneExecuteResponseHandler::createExecuteHandler(
373                 const SceneCollectionResource::Ptr ptr, SceneExecuteCallback executeCB)
374         {
375             auto executeHandler = std::make_shared<SceneExecuteResponseHandler>();
376
377             executeHandler->m_numOfMembers = ptr->m_SceneMembers.size();
378             executeHandler->m_responseMembers = 0;
379
380             executeHandler->m_Cb = std::bind(
381                     &SceneCollectionResource::onExecute, ptr,
382                     std::placeholders::_1, std::move(executeCB), executeHandler);
383
384             executeHandler->m_Owner
385                 = std::weak_ptr<SceneCollectionResource>(ptr);
386             executeHandler->m_errorCode  = SCENE_RESPONSE_SUCCESS;
387
388             return executeHandler;
389         }
390     }
391 }