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