Imported Upstream version 1.2.0
[platform/upstream/iotivity.git] / service / simulator / src / server / simulator_resource_factory.cpp
1 /******************************************************************\r
2  *\r
3  * Copyright 2015 Samsung Electronics All Rights Reserved.\r
4  *\r
5  *\r
6  *\r
7  * Licensed under the Apache License, Version 2.0 (the "License");\r
8  * you may not use this file except in compliance with the License.\r
9  * You may obtain a copy of the License at\r
10  *\r
11  *      http://www.apache.org/licenses/LICENSE-2.0\r
12  *\r
13  * Unless required by applicable law or agreed to in writing, software\r
14  * distributed under the License is distributed on an "AS IS" BASIS,\r
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
16  * See the License for the specific language governing permissions and\r
17  * limitations under the License.\r
18  *\r
19  ******************************************************************/\r
20 \r
21 #include "simulator_resource_factory.h"\r
22 #include "simulator_single_resource_impl.h"\r
23 #include "simulator_collection_resource_impl.h"\r
24 #include "simulator_logger.h"\r
25 #include "logger.h"\r
26 #include "request_model_builder.h"\r
27 \r
28 #define TAG "SIM_RESOURCE_FACTORY"\r
29 \r
30 SimulatorResourceFactory *SimulatorResourceFactory::getInstance()\r
31 {\r
32     static SimulatorResourceFactory s_instance;\r
33     return &s_instance;\r
34 }\r
35 \r
36 std::shared_ptr<SimulatorResource> SimulatorResourceFactory::createResource(\r
37     const std::string &configPath)\r
38 {\r
39     // Parse the RAML file\r
40     std::shared_ptr<RAML::RamlParser> ramlParser = std::make_shared<RAML::RamlParser>(configPath);\r
41     if (!ramlParser)\r
42     {\r
43         OIC_LOG(ERROR, TAG, "RAML parser returned NULL!");\r
44         return nullptr;\r
45     }\r
46 \r
47     RAML::RamlPtr raml = ramlParser->getRamlPtr();\r
48     if (!raml)\r
49     {\r
50         OIC_LOG(ERROR, TAG, "RAML pointer is NULL!");\r
51         return nullptr;\r
52     }\r
53 \r
54     // Get the first resource model from RAML\r
55     RAML::RamlResourcePtr ramlResource;\r
56     if (0 == raml->getResources().size()\r
57         || nullptr == (ramlResource = raml->getResources().begin()->second))\r
58     {\r
59         OIC_LOG(ERROR, TAG, "Zero resources detected from RAML!");\r
60         return nullptr;\r
61     }\r
62 \r
63     return buildResource(ramlResource);\r
64 }\r
65 \r
66 std::vector<std::shared_ptr<SimulatorResource> > SimulatorResourceFactory::createResource(\r
67     const std::string &configPath, unsigned int count)\r
68 {\r
69     std::vector<std::shared_ptr<SimulatorResource>> resources;\r
70 \r
71     // Parse the RAML file\r
72     std::shared_ptr<RAML::RamlParser> ramlParser = std::make_shared<RAML::RamlParser>(configPath);\r
73     if (!ramlParser)\r
74     {\r
75         OIC_LOG(ERROR, TAG, "RAML parser returned NULL!");\r
76         return resources;\r
77     }\r
78 \r
79     RAML::RamlPtr raml = ramlParser->getRamlPtr();\r
80     if (!raml)\r
81     {\r
82         OIC_LOG(ERROR, TAG, "RAML pointer is NULL!");\r
83         return resources;\r
84     }\r
85 \r
86     // Get the first resource model from RAML\r
87     RAML::RamlResourcePtr ramlResource;\r
88     if (0 == raml->getResources().size()\r
89         || nullptr == (ramlResource = raml->getResources().begin()->second))\r
90     {\r
91         OIC_LOG(ERROR, TAG, "Zero resources detected from RAML!");\r
92         return resources;\r
93     }\r
94 \r
95     while (count--)\r
96     {\r
97         std::shared_ptr<SimulatorResource> resource = buildResource(ramlResource);\r
98         if (!resource)\r
99         {\r
100             OIC_LOG(ERROR, TAG, "Failed to create resource!");\r
101             return resources;\r
102         }\r
103 \r
104         resources.push_back(resource);\r
105     }\r
106 \r
107     return resources;\r
108 }\r
109 \r
110 std::shared_ptr<SimulatorSingleResource> SimulatorResourceFactory::createSingleResource(\r
111     const std::string &name, const std::string &uri, const std::string &resourceType)\r
112 {\r
113     SimulatorSingleResourceImpl *simpleResource = new SimulatorSingleResourceImpl();\r
114     simpleResource->setName(name);\r
115     simpleResource->setURI(uri);\r
116     simpleResource->setResourceType(resourceType);\r
117     return std::shared_ptr<SimulatorSingleResource>(simpleResource);\r
118 }\r
119 \r
120 std::shared_ptr<SimulatorCollectionResource> SimulatorResourceFactory::createCollectionResource(\r
121     const std::string &name, const std::string &uri, const std::string &resourceType)\r
122 {\r
123     SimulatorCollectionResourceImpl *collectionResource = new SimulatorCollectionResourceImpl();\r
124     collectionResource->setName(name);\r
125     collectionResource->setURI(uri);\r
126     collectionResource->setResourceType(resourceType);\r
127     return std::shared_ptr<SimulatorCollectionResource>(collectionResource);\r
128 }\r
129 \r
130 std::shared_ptr<SimulatorResource> SimulatorResourceFactory::buildResource(\r
131     const std::shared_ptr<RAML::RamlResource> &ramlResource)\r
132 {\r
133     // Build resource request and respone model schema\r
134     RequestModelBuilder requestModelBuilder;\r
135     std::unordered_map<std::string, RequestModelSP> requestModels =\r
136         requestModelBuilder.build(ramlResource);\r
137 \r
138     // Build SimulatorResourceModel from "GET" response schema\r
139     if (requestModels.end() == requestModels.find("GET"))\r
140     {\r
141         OIC_LOG(ERROR, TAG, "Resource's RAML does not have GET request model!");\r
142         return nullptr;\r
143     }\r
144 \r
145     RequestModelSP getRequestModel = requestModels["GET"];\r
146     ResponseModelSP getResponseModel = getRequestModel->getResponseModel(200);\r
147     if (!getResponseModel)\r
148     {\r
149         OIC_LOG(ERROR, TAG, "Resource's RAML does not have response for GET request!");\r
150         return nullptr;\r
151     }\r
152 \r
153     std::shared_ptr<SimulatorResourceModelSchema> responseSchema =\r
154         getResponseModel->getSchema();\r
155     if (!responseSchema)\r
156     {\r
157         OIC_LOG(ERROR, TAG, "Failed to get schema from response model!");\r
158         return nullptr;\r
159     }\r
160 \r
161     SimulatorResourceModel resourceModel = responseSchema->buildResourceModel();\r
162 \r
163     // Remove the common properties from  resource Model\r
164     std::string resourceURI = ramlResource->getResourceUri();\r
165     std::string resourceName = ramlResource->getDisplayName();\r
166     std::string resourceType;\r
167 \r
168     // Extracting resource type.\r
169     if (resourceModel.contains("rt"))\r
170     {\r
171         resourceType = resourceModel.get<std::string>("rt");\r
172         resourceModel.remove("rt");\r
173     }\r
174     else if (resourceModel.contains("resourceType"))\r
175     {\r
176         resourceType = resourceModel.get<std::string>("resourceType");\r
177         resourceModel.remove("resourceType");\r
178     }\r
179 \r
180     // Extracting interface type.\r
181     std::vector<std::string> interfaceTypes;\r
182     if (resourceModel.contains("if"))\r
183     {\r
184         SimulatorResourceModel::TypeInfo typeInfo = resourceModel.getType("if");\r
185         if(AttributeValueType::STRING == typeInfo.type())\r
186         {\r
187             interfaceTypes.push_back(resourceModel.get<std::string>("if"));\r
188         }\r
189         else if(AttributeValueType::VECTOR == typeInfo.type()\r
190             && AttributeValueType::STRING == typeInfo.baseType()\r
191             && typeInfo.depth() == 1)\r
192         {\r
193             interfaceTypes = resourceModel.get<std::vector<std::string>>("if");\r
194             if (interfaceTypes.size() > 1)\r
195                 interfaceTypes.erase(interfaceTypes.begin()+1, interfaceTypes.end());\r
196         }\r
197 \r
198         resourceModel.remove("if");\r
199     }\r
200 \r
201     for (auto &requestModel : requestModels)\r
202     {\r
203         if (requestModel.second)\r
204         {\r
205             addInterfaceFromQueryParameter((requestModel.second)->getQueryParams("if"),\r
206                 interfaceTypes);\r
207         }\r
208     }\r
209 \r
210     // Remove properties which are not part of resource representation\r
211     resourceModel.remove("p");\r
212     resourceModel.remove("n");\r
213     resourceModel.remove("id");\r
214 \r
215     // Create simple/collection resource\r
216     std::shared_ptr<SimulatorResource> simResource;\r
217     if (resourceModel.contains("links"))\r
218     {\r
219         std::shared_ptr<SimulatorCollectionResourceImpl> collectionRes(\r
220             new SimulatorCollectionResourceImpl());\r
221 \r
222         collectionRes->setName(resourceName);\r
223         if(!resourceType.empty())\r
224             collectionRes->setResourceType(resourceType);\r
225         if (interfaceTypes.size() > 0)\r
226             collectionRes->setInterface(interfaceTypes);\r
227         collectionRes->setURI(ResourceURIFactory::getInstance()->makeUniqueURI(resourceURI));\r
228 \r
229         // Set the resource model and its schema to simulated resource\r
230         collectionRes->setResourceModel(resourceModel);\r
231         collectionRes->setResourceModelSchema(responseSchema);\r
232         collectionRes->setRequestModel(requestModels);\r
233 \r
234         simResource = collectionRes;\r
235     }\r
236     else\r
237     {\r
238         std::shared_ptr<SimulatorSingleResourceImpl> singleRes(\r
239             new SimulatorSingleResourceImpl());\r
240 \r
241         singleRes->setName(resourceName);\r
242         if(!resourceType.empty())\r
243             singleRes->setResourceType(resourceType);\r
244         if (interfaceTypes.size() > 0)\r
245             singleRes->setInterface(interfaceTypes);\r
246         singleRes->setURI(ResourceURIFactory::getInstance()->makeUniqueURI(resourceURI));\r
247 \r
248         // Set the resource model and its schema to simulated resource\r
249         singleRes->setResourceModel(resourceModel);\r
250         singleRes->setResourceModelSchema(responseSchema);\r
251         singleRes->setRequestModel(requestModels);\r
252 \r
253         simResource = singleRes;\r
254     }\r
255 \r
256     return simResource;\r
257 }\r
258 \r
259 void SimulatorResourceFactory::addInterfaceFromQueryParameter(\r
260     std::vector<std::string> queryParamValue, std::vector<std::string> &interfaceTypes)\r
261 {\r
262     for (auto &interfaceType : queryParamValue)\r
263     {\r
264         if (interfaceTypes.end() ==\r
265             std::find(interfaceTypes.begin(), interfaceTypes.end(), interfaceType))\r
266         {\r
267             interfaceTypes.push_back(interfaceType);\r
268         }\r
269     }\r
270 }\r
271 \r
272 ResourceURIFactory *ResourceURIFactory::getInstance()\r
273 {\r
274     static ResourceURIFactory s_instance;\r
275     return &s_instance;\r
276 }\r
277 \r
278 ResourceURIFactory::ResourceURIFactory()\r
279     : m_id(0) {}\r
280 \r
281 std::string ResourceURIFactory::makeUniqueURI(const std::string &uri)\r
282 {\r
283     std::lock_guard<std::mutex> lock(m_lock);\r
284     if (isUnique(uri))\r
285     {\r
286         updateUri(uri);\r
287         return uri;\r
288     }\r
289     std::ostringstream os;\r
290     os << uri;\r
291     if (!uri.empty() && '/' != uri[uri.length() - 1])\r
292         os << '/';\r
293     os << m_id++;\r
294     updateUri(os.str());\r
295     return os.str();\r
296 }\r
297 \r
298 void ResourceURIFactory::updateUri(const std::string &uri)\r
299 {\r
300     m_uriList.insert(std::pair<std::string, bool>(uri, true));\r
301 }\r
302 \r
303 bool ResourceURIFactory::isUnique(const std::string &uri)\r
304 {\r
305     if (m_uriList.end() == m_uriList.find(uri))\r
306         return true;\r
307     else\r
308         return false;\r
309 }\r
310 \r