Fix for SVACE and Klocwork issues.
[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     RAML::RamlPtr raml = ramlParser->getRamlPtr();\r
42 \r
43     // Get the first resource model from RAML\r
44     RAML::RamlResourcePtr ramlResource;\r
45     if (0 == raml->getResources().size()\r
46         || nullptr == (ramlResource = raml->getResources().begin()->second))\r
47     {\r
48         OC_LOG(ERROR, TAG, "Zero resources detected from RAML!");\r
49         return nullptr;\r
50     }\r
51 \r
52     return buildResource(ramlResource);\r
53 }\r
54 \r
55 std::vector<std::shared_ptr<SimulatorResource> > SimulatorResourceFactory::createResource(\r
56     const std::string &configPath, unsigned int count)\r
57 {\r
58     std::vector<std::shared_ptr<SimulatorResource>> resources;\r
59 \r
60     // Parse the RAML file\r
61     std::shared_ptr<RAML::RamlParser> ramlParser = std::make_shared<RAML::RamlParser>(configPath);\r
62     RAML::RamlPtr raml = ramlParser->getRamlPtr();\r
63 \r
64     // Get the first resource model from RAML\r
65     RAML::RamlResourcePtr ramlResource;\r
66     if (0 == raml->getResources().size()\r
67         || nullptr == (ramlResource = raml->getResources().begin()->second))\r
68     {\r
69         OC_LOG(ERROR, TAG, "Zero resources detected from RAML!");\r
70         return resources;\r
71     }\r
72 \r
73     while (count--)\r
74     {\r
75         std::shared_ptr<SimulatorResource> resource = buildResource(ramlResource);\r
76         if (!resource)\r
77         {\r
78             OC_LOG(ERROR, TAG, "Failed to create resource!");\r
79             return resources;\r
80         }\r
81 \r
82         resources.push_back(resource);\r
83     }\r
84 \r
85     return resources;\r
86 }\r
87 \r
88 std::shared_ptr<SimulatorSingleResource> SimulatorResourceFactory::createSingleResource(\r
89     const std::string &name, const std::string &uri, const std::string &resourceType)\r
90 {\r
91     SimulatorSingleResourceImpl *simpleResource = new SimulatorSingleResourceImpl();\r
92     simpleResource->setName(name);\r
93     simpleResource->setURI(uri);\r
94     simpleResource->setResourceType(resourceType);\r
95     return std::shared_ptr<SimulatorSingleResource>(simpleResource);\r
96 }\r
97 \r
98 std::shared_ptr<SimulatorCollectionResource> SimulatorResourceFactory::createCollectionResource(\r
99     const std::string &name, const std::string &uri, const std::string &resourceType)\r
100 {\r
101     SimulatorCollectionResourceImpl *collectionResource = new SimulatorCollectionResourceImpl();\r
102     collectionResource->setName(name);\r
103     collectionResource->setURI(uri);\r
104     collectionResource->setResourceType(resourceType);\r
105     return std::shared_ptr<SimulatorCollectionResource>(collectionResource);\r
106 }\r
107 \r
108 std::shared_ptr<SimulatorResource> SimulatorResourceFactory::buildResource(\r
109     const std::shared_ptr<RAML::RamlResource> &ramlResource)\r
110 {\r
111     // Build resource request and respone model schema\r
112     RequestModelBuilder requestModelBuilder;\r
113     std::unordered_map<std::string, RequestModelSP> requestModels =\r
114         requestModelBuilder.build(ramlResource);\r
115 \r
116     // Build SimulatorResourceModel from "GET" response schema\r
117     if (requestModels.end() == requestModels.find("GET"))\r
118     {\r
119         OC_LOG(ERROR, TAG, "Resource's RAML does not have GET request model!");\r
120         return nullptr;\r
121     }\r
122 \r
123     RequestModelSP getRequestModel = requestModels["GET"];\r
124     ResponseModelSP getResponseModel = getRequestModel->getResponseModel(200);\r
125     if (!getResponseModel)\r
126     {\r
127         OC_LOG(ERROR, TAG, "Resource's RAML does not have response for GET request!");\r
128         return nullptr;\r
129     }\r
130 \r
131     std::shared_ptr<SimulatorResourceModelSchema> responseSchema =\r
132         getResponseModel->getSchema();\r
133     if (!responseSchema)\r
134     {\r
135         OC_LOG(ERROR, TAG, "Failed to get schema from response model!");\r
136         return nullptr;\r
137     }\r
138 \r
139     SimulatorResourceModel resourceModel = responseSchema->buildResourceModel();\r
140 \r
141     // Remove the common properties from  resource Model\r
142     std::string resourceURI = ramlResource->getResourceUri();\r
143     std::string resourceName = ramlResource->getDisplayName();\r
144     std::string resourceType;\r
145 \r
146     // Extracting resource type.\r
147     if (resourceModel.contains("rt"))\r
148     {\r
149         resourceType = resourceModel.get<std::string>("rt");\r
150         resourceModel.remove("rt");\r
151     }\r
152     else if (resourceModel.contains("resourceType"))\r
153     {\r
154         resourceType = resourceModel.get<std::string>("resourceType");\r
155         resourceModel.remove("resourceType");\r
156     }\r
157 \r
158     // Construct resource type from uri\r
159     if(resourceType.empty())\r
160     {\r
161         std::ostringstream rtString;\r
162         rtString << "oic.r.";\r
163 \r
164         size_t pos = resourceURI.rfind("/");\r
165         if (pos == std::string::npos)\r
166             pos = -1;\r
167 \r
168         std::string rtName = resourceURI.substr(pos+1);\r
169         std::transform(rtName.begin(), rtName.end(), rtName.begin(), ::tolower);\r
170         rtString << rtName;\r
171         resourceType = rtString.str();\r
172     }\r
173 \r
174     // Extracting interface type.\r
175     std::vector<std::string> interfaceTypes;\r
176     if (resourceModel.contains("if"))\r
177     {\r
178         SimulatorResourceModel::TypeInfo typeInfo = resourceModel.getType("if");\r
179         if(AttributeValueType::STRING == typeInfo.type())\r
180         {\r
181             interfaceTypes.push_back(resourceModel.get<std::string>("if"));\r
182         }\r
183         else if(AttributeValueType::VECTOR == typeInfo.type()\r
184             && AttributeValueType::STRING == typeInfo.baseType()\r
185             && typeInfo.depth() == 1)\r
186         {\r
187             interfaceTypes = resourceModel.get<std::vector<std::string>>("if");\r
188             if (interfaceTypes.size() > 1)\r
189                 interfaceTypes.erase(interfaceTypes.begin()+1, interfaceTypes.end());\r
190         }\r
191 \r
192         resourceModel.remove("if");\r
193     }\r
194 \r
195     for (auto &requestModel : requestModels)\r
196     {\r
197         if (requestModel.second)\r
198         {\r
199             addInterfaceFromQueryParameter((requestModel.second)->getQueryParams("if"),\r
200                 interfaceTypes);\r
201         }\r
202     }\r
203 \r
204     // Remove properties which are not part of resource representation\r
205     resourceModel.remove("p");\r
206     resourceModel.remove("n");\r
207     resourceModel.remove("id");\r
208 \r
209     // Create simple/collection resource\r
210     std::shared_ptr<SimulatorResource> simResource;\r
211     if (resourceModel.contains("links"))\r
212     {\r
213         std::shared_ptr<SimulatorCollectionResourceImpl> collectionRes(\r
214             new SimulatorCollectionResourceImpl());\r
215 \r
216         collectionRes->setName(resourceName);\r
217         collectionRes->setResourceType(resourceType);\r
218         if (interfaceTypes.size() > 0)\r
219             collectionRes->setInterface(interfaceTypes);\r
220         collectionRes->setURI(ResourceURIFactory::getInstance()->makeUniqueURI(resourceURI));\r
221 \r
222         // Set the resource model and its schema to simulated resource\r
223         collectionRes->setResourceModel(resourceModel);\r
224         collectionRes->setResourceModelSchema(responseSchema);\r
225         collectionRes->setRequestModel(requestModels);\r
226 \r
227         simResource = collectionRes;\r
228     }\r
229     else\r
230     {\r
231         std::shared_ptr<SimulatorSingleResourceImpl> singleRes(\r
232             new SimulatorSingleResourceImpl());\r
233 \r
234         singleRes->setName(resourceName);\r
235         singleRes->setResourceType(resourceType);\r
236         if (interfaceTypes.size() > 0)\r
237             singleRes->setInterface(interfaceTypes);\r
238         singleRes->setURI(ResourceURIFactory::getInstance()->makeUniqueURI(resourceURI));\r
239 \r
240         // Set the resource model and its schema to simulated resource\r
241         singleRes->setResourceModel(resourceModel);\r
242         singleRes->setResourceModelSchema(responseSchema);\r
243         singleRes->setRequestModel(requestModels);\r
244 \r
245         simResource = singleRes;\r
246     }\r
247 \r
248     return simResource;\r
249 }\r
250 \r
251 void SimulatorResourceFactory::addInterfaceFromQueryParameter(\r
252     std::vector<std::string> queryParamValue, std::vector<std::string> &interfaceTypes)\r
253 {\r
254     for (auto &interfaceType : queryParamValue)\r
255     {\r
256         if (interfaceTypes.end() ==\r
257             std::find(interfaceTypes.begin(), interfaceTypes.end(), interfaceType))\r
258         {\r
259             interfaceTypes.push_back(interfaceType);\r
260         }\r
261     }\r
262 }\r
263 \r
264 ResourceURIFactory *ResourceURIFactory::getInstance()\r
265 {\r
266     static ResourceURIFactory s_instance;\r
267     return &s_instance;\r
268 }\r
269 \r
270 ResourceURIFactory::ResourceURIFactory()\r
271     : m_id(0) {}\r
272 \r
273 std::string ResourceURIFactory::makeUniqueURI(const std::string &uri)\r
274 {\r
275     std::lock_guard<std::mutex> lock(m_lock);\r
276     if (isUnique(uri))\r
277     {\r
278         updateUri(uri);\r
279         return uri;\r
280     }\r
281     std::ostringstream os;\r
282     os << uri;\r
283     if (!uri.empty() && '/' != uri[uri.length() - 1])\r
284         os << '/';\r
285     os << m_id++;\r
286     updateUri(os.str());\r
287     return os.str();\r
288 }\r
289 \r
290 void ResourceURIFactory::updateUri(const std::string &uri)\r
291 {\r
292     m_uriList.insert(std::pair<std::string, bool>(uri, true));\r
293 }\r
294 \r
295 bool ResourceURIFactory::isUnique(const std::string &uri)\r
296 {\r
297     if (m_uriList.end() == m_uriList.find(uri))\r
298         return true;\r
299     else\r
300         return false;\r
301 }\r
302 \r