Remove a Things Manager class and expose its component classes for SDK
[platform/upstream/iotivity.git] / service / things-manager / sdk / src / ThingsMaintenance.cpp
1 //******************************************************************
2 //
3 // Copyright 2014 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 /**
22  * @file
23  *
24  */
25
26 #include <OCApi.h>
27 #include <OCPlatform.h>
28 #include <cstdlib>
29
30 #include "ThingsMaintenance.h"
31
32 using namespace OC;
33
34 namespace OIC
35 {
36     std::map< std::string, MaintenanceRequestEntry > maintenanceRequestTable;
37     ThingsMaintenance* ThingsMaintenance::thingsMaintenanceInstance = NULL;
38
39     MaintenanceRequestEntry::MaintenanceRequestEntry(std::string ID, MaintenanceCallback callback,
40                 std::shared_ptr< OCResource > resource, std::string updateVal)
41     {
42         m_ID = ID;
43         m_callback = callback;
44         m_resource = resource;
45         m_updateVal = updateVal;
46     }
47
48     MaintenanceUnitInfo::MaintenanceUnitInfo(std::string name,
49                                             std::string attribute,
50                                             std::string uri)
51     {
52         m_name = name;
53         m_attribute = attribute;
54         m_uri = uri;
55     }
56
57     std::string MaintenanceUnitInfo::getJSON()
58     {
59         std::string res;
60
61         res = "{\"name\":\"" + m_name + "\",\"attribute\":\"" + m_attribute + "\"}";
62
63         return res;
64     }
65
66     ThingsMaintenance::ThingsMaintenance()
67     {
68         MaintenanceUnitInfo unit[] =
69                 {
70                 { "rb", "Reboot", "/oic/mnt"},
71                 { "ssc", "StartStatCollection", "/oic/mnt"},
72                 { "fr", "Factory Reset", "/oic/mnt" } };
73
74         for (int i = 0; i < NUMDIAGUNIT; i++)
75             MaintenanceUnitTable.push_back(unit[i]);
76     }
77
78     ThingsMaintenance::~ThingsMaintenance()
79     {
80     }
81
82     void ThingsMaintenance::setGroupManager(GroupManager *groupmanager)
83     {
84         g_groupmanager = groupmanager;
85     }
86
87     ThingsMaintenance* ThingsMaintenance::getInstance()
88     {
89         if (thingsMaintenanceInstance == NULL)
90         {
91             thingsMaintenanceInstance = new ThingsMaintenance();
92         }
93         return thingsMaintenanceInstance;
94     }
95
96     void ThingsMaintenance::deleteInstance()
97     {
98         if (thingsMaintenanceInstance)
99         {
100             delete thingsMaintenanceInstance;
101             thingsMaintenanceInstance = NULL;
102         }
103     }
104
105     std::string ThingsMaintenance::getAttributeByMaintenanceName(MaintenanceName name)
106     {
107         for (auto it = MaintenanceUnitTable.begin(); MaintenanceUnitTable.end() != it; it++)
108         {
109             if ((*it).m_name == name)
110                 return (*it).m_attribute;
111         }
112
113         return "";
114     }
115
116     std::string ThingsMaintenance::getUriByMaintenanceName(MaintenanceName name)
117     {
118         for (auto it = MaintenanceUnitTable.begin(); MaintenanceUnitTable.end() != it; it++)
119         {
120             if ((*it).m_name == name)
121                 return (*it).m_uri;
122         }
123
124         return "";
125     }
126
127     std::string ThingsMaintenance::getUpdateVal(std::string mnt)
128     {
129         std::map< std::string, MaintenanceRequestEntry >::iterator it =
130                 maintenanceRequestTable.find(mnt);
131
132         if (it == maintenanceRequestTable.end())
133             return NULL;
134         else
135             return it->second.m_updateVal;
136
137     }
138     std::shared_ptr< OCResource > ThingsMaintenance::getResource(std::string mnt)
139     {
140         std::map< std::string, MaintenanceRequestEntry >::iterator it =
141                 maintenanceRequestTable.find(mnt);
142
143         if (it == maintenanceRequestTable.end())
144             return NULL;
145         else
146             return it->second.m_resource;
147     }
148
149     MaintenanceCallback ThingsMaintenance::getCallback(std::string mnt)
150     {
151         std::map< std::string, MaintenanceRequestEntry >::iterator it =
152                 maintenanceRequestTable.find(mnt);
153
154         if (it == maintenanceRequestTable.end())
155             return NULL;
156         else
157             return it->second.m_callback;
158     }
159
160     std::string ThingsMaintenance::getHostFromURI(std::string oldUri)
161     {
162         size_t f;
163         std::string newUri;
164
165         if ((f = oldUri.find("/factoryset/oic/")) != string::npos)
166             newUri = oldUri.replace(f, oldUri.size(), "");
167         else if ((f = oldUri.find("/oic/")) != string::npos)
168             newUri = oldUri.replace(f, oldUri.size(), "");
169
170         return newUri;
171     }
172
173     std::string ThingsMaintenance::getListOfSupportedMaintenanceUnits()
174     {
175         std::string res;
176
177         res = "{\"Maintenance Units\":[";
178
179         auto it = MaintenanceUnitTable.begin();
180         while (1)
181         {
182             res = res + (*it).getJSON();
183             it++;
184
185             if (it == MaintenanceUnitTable.end())
186                 break;
187             else
188                 res += ",";
189         }
190
191         res += "]}";
192
193         return res;
194     }
195
196     void ThingsMaintenance::onGetChildInfoForUpdate(const HeaderOptions& headerOptions,
197             const OCRepresentation& rep, const int eCode, std::string mnt)
198     {
199         if (eCode != OC_STACK_OK)
200         {
201             std::cout << "onGet Response error: " << eCode << std::endl;
202             getCallback(mnt)(headerOptions, rep, eCode);
203             return ;
204         }
205
206         std::cout << "GET request was successful" << std::endl;
207
208         std::cout << "\tResource URI: " << rep.getUri() << std::endl;
209
210         std::vector < OCRepresentation > children = rep.getChildren();
211         for (auto oit = children.begin(); oit != children.end(); ++oit)
212         {
213             std::cout << "\t\tChild Resource URI: " << oit->getUri() << std::endl;
214         }
215
216         // Get information by using maintenance name(mnt)
217         std::shared_ptr < OCResource > resource = getResource(mnt);
218         std::string actionstring = mnt;
219         std::string uri = getUriByMaintenanceName(mnt);
220         std::string attrKey = mnt;
221
222         if (uri == "")
223             return;
224
225         if (resource)
226         {
227             // In this nest, we create a new action set of which name is the dignostics name.
228             // Required information consists of a host address, URI, attribute key, and
229             // attribute value.
230             ActionSet *newActionSet = new ActionSet();
231             newActionSet->actionsetName = mnt;
232
233             for (auto oit = children.begin(); oit != children.end(); ++oit)
234             {
235                 Action *newAction = new Action();
236
237                 // oit->getUri() includes a host address as well as URI.
238                 // We should split these to each other and only use the host address to create
239                 // a child resource's URI. Note that the collection resource and its child
240                 // resource are located in same host.
241                 newAction->target = getHostFromURI(oit->getUri()) + uri;
242
243                 Capability *newCapability = new Capability();
244                 newCapability->capability = attrKey;
245                 newCapability->status = getUpdateVal(mnt);
246
247                 newAction->listOfCapability.push_back(newCapability);
248                 newActionSet->listOfAction.push_back(newAction);
249             }
250
251             // Request to create a new action set by using the above actionSet
252             g_groupmanager->addActionSet(resource, newActionSet,
253                     std::function<
254                             void(const HeaderOptions& headerOptions,
255                                     const OCRepresentation& rep, const int eCode) >(
256                             std::bind(&ThingsMaintenance::onCreateActionSet, this,
257                                     std::placeholders::_1, std::placeholders::_2,
258                                     std::placeholders::_3, mnt)));
259
260             delete(newActionSet);
261
262         }
263     }
264
265     void ThingsMaintenance::onCreateActionSet(const HeaderOptions& headerOptions,
266             const OCRepresentation& rep, const int eCode, std::string mnt)
267     {
268         if (eCode != OC_STACK_OK)
269         {
270             std::cout << "onPut Response error: " << eCode << std::endl;
271             getCallback(mnt)(headerOptions, rep, eCode);
272             return ;
273         }
274
275         std::cout << "PUT request was successful" << std::endl;
276
277         std::shared_ptr < OCResource > resource = getResource(mnt);
278         if (resource)
279         {
280             // Now, it is time to execute the action set.
281             g_groupmanager->executeActionSet(resource, mnt,
282                     std::function<
283                             void(const HeaderOptions& headerOptions,
284                                     const OCRepresentation& rep, const int eCode) >(
285                             std::bind(&ThingsMaintenance::onExecuteForGroupAction, this,
286                                     std::placeholders::_1, std::placeholders::_2,
287                                     std::placeholders::_3, mnt)));
288         }
289     }
290
291     void ThingsMaintenance::onExecuteForGroupAction(const HeaderOptions& headerOptions,
292             const OCRepresentation& rep, const int eCode, std::string mnt)
293     {
294         if (eCode != OC_STACK_OK)
295         {
296             std::cout << "onPut Response error: " << eCode << std::endl;
297             getCallback(mnt)(headerOptions, rep, eCode);
298             return ;
299         }
300
301         std::cout << "PUT request was successful" << std::endl;
302         getCallback(mnt)(headerOptions, rep, eCode);
303
304         // Delete the created actionset
305         std::shared_ptr < OCResource > resource = getResource(mnt);
306         if (resource)
307         {
308             g_groupmanager->deleteActionSet(resource, mnt,
309                     std::function<
310                             void(const HeaderOptions& headerOptions,
311                                     const OCRepresentation& rep, const int eCode) >(
312                             std::bind(&ThingsMaintenance::onDeleteGroupAction, this,
313                                     std::placeholders::_1, std::placeholders::_2,
314                                     std::placeholders::_3, mnt)));
315         }
316     }
317
318     void ThingsMaintenance::onDeleteGroupAction(const HeaderOptions& headerOptions,
319             const OCRepresentation& rep, const int eCode, std::string mnt)
320     {
321         if (eCode != OC_STACK_OK)
322         {
323             std::cout << "Delete actionset returned with error: " << eCode << mnt << std::endl;
324             return;
325         }
326
327         std::cout << "Deleted the actionset created!" << mnt<< std::endl;
328     }
329
330     void ThingsMaintenance::onPut(const HeaderOptions& headerOptions, const OCRepresentation& rep,
331             const int eCode, std::string mnt)
332     {
333         if (eCode != OC_STACK_OK)
334         {
335             std::cout << "onPut Response error: " << eCode << std::endl;
336             getCallback(mnt)(headerOptions, rep, eCode);
337             return ;
338         }
339
340         std::cout << "PUT request was successful" << std::endl;
341
342         getCallback(mnt)(headerOptions, rep, eCode);
343
344     }
345
346     bool ThingsMaintenance::isSimpleResource(std::shared_ptr< OCResource > resource)
347     {
348         for (unsigned int i = 0; i < resource->getResourceTypes().size(); ++i)
349         {
350             if (resource->getResourceTypes().at(0).find(".resourceset", 0) != std::string::npos)
351                 return false;
352         }
353
354         return true;
355     }
356
357     OCStackResult ThingsMaintenance::reboot(std::shared_ptr< OCResource > resource,
358             MaintenanceCallback callback)
359     {
360         if (!resource)
361         {
362             std::cout << "resource is NULL\n";
363             return OC_STACK_ERROR;
364         }
365
366         std::string mnt = "rb";
367
368         // Check the request queue if a previous request is still left. If so, remove it.
369         std::map< std::string, MaintenanceRequestEntry >::iterator iter =
370                 maintenanceRequestTable.find(mnt);
371         if (iter != maintenanceRequestTable.end())
372             maintenanceRequestTable.erase(iter);
373
374         // Create new request entry stored in the queue
375         MaintenanceRequestEntry newCallback(mnt, callback, resource, "true");
376         maintenanceRequestTable.insert(std::make_pair(mnt, newCallback));
377
378         QueryParamsMap query;
379         OCRepresentation rep;
380
381         if (isSimpleResource(resource))
382         {
383             // This resource is a simple resource. Just send a PUT message
384             OCRepresentation rep;
385             rep.setValue < std::string > (mnt, "true");
386
387             return resource->put(resource->getResourceTypes().at(0), DEFAULT_INTERFACE, rep, query,
388                     std::function<
389                             void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
390                                     const int eCode) >(
391                             std::bind(&ThingsMaintenance::onPut, this, std::placeholders::_1,
392                                     std::placeholders::_2, std::placeholders::_3, mnt)));
393         }
394         else
395         {
396             // This resource is a collection resource. It just acquires child resource's URI and
397             // send GET massages to the child resources in turn.
398             // First, request the child resources's URI.
399             // TODO: Add a deletion of actionset
400             return resource->get(resource->getResourceTypes().at(0), DEFAULT_INTERFACE, query,
401                     std::function<
402                             void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
403                                     const int eCode) >(
404                             std::bind(&ThingsMaintenance::onGetChildInfoForUpdate, this,
405                                     std::placeholders::_1, std::placeholders::_2,
406                                     std::placeholders::_3, mnt)));
407         }
408     }
409
410     OCStackResult ThingsMaintenance::factoryReset(std::shared_ptr< OCResource > resource,
411             MaintenanceCallback callback)
412     {
413         if (!resource)
414         {
415             std::cout << "resource is NULL\n";
416             return OC_STACK_ERROR;
417         }
418
419         std::string mnt = "fr";
420
421         // Check the request queue if a previous request is still left. If so, remove it.
422         std::map< std::string, MaintenanceRequestEntry >::iterator iter =
423                 maintenanceRequestTable.find(mnt);
424         if (iter != maintenanceRequestTable.end())
425             maintenanceRequestTable.erase(iter);
426
427         // Create new request entry stored in the queue
428         MaintenanceRequestEntry newCallback(mnt, callback, resource, "true");
429         maintenanceRequestTable.insert(std::make_pair(mnt, newCallback));
430
431         QueryParamsMap query;
432         OCRepresentation rep;
433
434         if (isSimpleResource(resource))
435         {
436             // This resource is a simple resource. Just send a PUT message
437             OCRepresentation rep;
438             rep.setValue < std::string > ("value", "true");
439
440             return resource->put(resource->getResourceTypes().at(0), DEFAULT_INTERFACE, rep, query,
441                     std::function<
442                             void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
443                                     const int eCode) >(
444                             std::bind(&ThingsMaintenance::onPut, this, std::placeholders::_1,
445                                     std::placeholders::_2, std::placeholders::_3, mnt)));
446         }
447         else
448         {
449             // This resource is a collection resource. It just acquires child resource's URI and
450             // send GET massages to the child resources in turn.
451             // First, request the child resources's URI.
452             // TODO: Add a deletion of actionset
453             return resource->get(resource->getResourceTypes().at(0), DEFAULT_INTERFACE, query,
454                     std::function<
455                             void(const HeaderOptions& headerOptions, const OCRepresentation& rep,
456                                     const int eCode) >(
457                             std::bind(&ThingsMaintenance::onGetChildInfoForUpdate, this,
458                                     std::placeholders::_1, std::placeholders::_2,
459                                     std::placeholders::_3, mnt)));
460         }
461     }
462 }
463