9a2002196d5a44baa7408e587b17449c4b3aa62a
[platform/upstream/iotivity.git] / service / simulator / src / common / request_model_builder.cpp
1 /******************************************************************
2  *
3  * Copyright 2015 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 "request_model_builder.h"
22 #include "logger.h"
23
24 #define TAG "REQ_MODEL_BUILDER"
25
26 RequestModelBuilder::RequestModelBuilder(std::shared_ptr<RAML::Raml> &raml)
27     : m_raml (raml) {}
28
29 std::map<RequestType, RequestModelSP> RequestModelBuilder::build(const std::string &uri)
30 {
31     std::map<RequestType, RequestModelSP> modelList;
32     if (!m_raml)
33     {
34         return modelList;
35     }
36
37     for (auto  & resource : m_raml->getResources())
38     {
39         // Pick the resource based on the resource uri.
40         if (std::string::npos == uri.find((resource.second)->getResourceUri()))
41             continue;
42
43         // Construcut Request and Response Model from RAML::Action
44         for (auto  & action :  (resource.second)->getActions())
45         {
46             RequestModelSP requestModel = createRequestModel(action.second);
47             if (requestModel)
48                 modelList[requestModel->type()] = requestModel;
49         }
50     }
51
52     return modelList;
53 }
54
55 RequestModelSP RequestModelBuilder::createRequestModel(const RAML::ActionPtr &action)
56 {
57     OC_LOG(DEBUG, TAG, "Creating request model");
58
59     // Validate the action type. Only GET, PUT, POST and DELETE are supported.
60     RAML::ActionType actionType = action->getType();
61     if (actionType != RAML::ActionType::GET
62         && actionType != RAML::ActionType::PUT
63         && actionType != RAML::ActionType::POST
64         && actionType != RAML::ActionType::DELETE)
65     {
66         OC_LOG(ERROR, TAG, "Failed to create request model as it is of unknown type!");
67         return nullptr;
68     }
69
70     // Construct RequestModel
71     RequestModelSP requestModel(new RequestModel(getRequestType(actionType)));
72
73     // Get the allowed query parameters of the request
74     for (auto & qpEntry : action->getQueryParameters())
75     {
76         for (auto & value :  (qpEntry.second)->getEnumeration())
77         {
78             requestModel->addQueryParam(qpEntry.first, value);
79         }
80     }
81
82     RAML::RequestResponseBodyPtr requestBody = action->getRequestBody("application/json");
83     SimulatorResourceModelSP repSchema = createRepSchema(requestBody);
84     requestModel->setRepSchema(repSchema);
85
86     // Corresponsing responses
87     for (auto  & responseEntry :  action->getResponses())
88     {
89         std::string codeStr = responseEntry.first;
90         int code = boost::lexical_cast<int>(codeStr);
91         ResponseModelSP responseModel = createResponseModel(code, responseEntry.second);
92         if (nullptr != responseModel)
93         {
94             requestModel->addResponseModel(code, responseModel);
95         }
96     }
97
98     return requestModel;
99 }
100
101 ResponseModelSP RequestModelBuilder::createResponseModel(int code,
102         const RAML::ResponsePtr &response)
103 {
104     ResponseModelSP responseModel(new ResponseModel(code));
105     RAML::RequestResponseBodyPtr responseBody = response->getResponseBody("application/json");
106     SimulatorResourceModelSP repSchema = createRepSchema(responseBody);
107     responseModel->setRepSchema(repSchema);
108     return responseModel;
109 }
110
111 SimulatorResourceModelSP RequestModelBuilder::createRepSchema(const RAML::RequestResponseBodyPtr
112         &rep)
113 {
114     if (!rep)
115     {
116         return nullptr;
117     }
118     RAML::SchemaPtr schema = rep->getSchema();
119     if (!schema)
120     {
121         return nullptr;
122     }
123
124     RAML::JsonSchemaPtr properties = schema->getProperties();
125     if (!properties || 0 == properties->getProperties().size())
126         return nullptr;
127
128     SimulatorResourceModelSP repSchema = std::make_shared<SimulatorResourceModel>();
129     for (auto & propertyEntry : properties->getProperties())
130     {
131         std::string propName = propertyEntry.second->getName();
132         if ("rt" == propName || "resourceType" == propName || "if" == propName
133             || "p" == propName || "n" == propName || "id" == propName)
134             continue;
135
136         int valueType = propertyEntry.second->getValueType();
137         switch (valueType)
138         {
139             case 0: // Integer
140                 {
141                     // Add the attribute with value
142                     repSchema->addAttribute(propertyEntry.second->getName(), propertyEntry.second->getValue<int>());
143
144                     // Set the range
145                     int min, max, multipleof;
146                     propertyEntry.second->getRange(min, max, multipleof);
147                     repSchema->setRange(propertyEntry.second->getName(), min, max);
148                 }
149                 break;
150
151             case 1: // Double
152                 {
153                     // Add the attribute with value
154                     repSchema->addAttribute(propertyEntry.second->getName(), propertyEntry.second->getValue<double>());
155
156                     std::vector<SimulatorResourceModel::Attribute::ValueVariant> propValues =
157                         propertyEntry.second->getAllowedValues();
158
159                     // TODO: Use RAML function once available
160                     if (0 < propertyEntry.second->getAllowedValuesSize())
161                     {
162                         std::vector<double> allowedValues;
163                         for (auto & propValue : propValues)
164                         {
165                             double value = boost::lexical_cast<double> (propValue);
166                             allowedValues.push_back(value);
167                         }
168                         repSchema->setAllowedValues(propertyEntry.second->getName(), allowedValues);
169                     }
170                 }
171                 break;
172
173             case 2: // Boolean
174                 {
175                     // Add the attribute with value
176                     repSchema->addAttribute(propertyEntry.second->getName(), propertyEntry.second->getValue<bool>());
177                 }
178                 break;
179
180             case 3: // String
181                 {
182                     // Add the attribute with value
183                     repSchema->addAttribute(propertyEntry.second->getName(),
184                                             propertyEntry.second->getValue<std::string>());
185
186                     std::vector<SimulatorResourceModel::Attribute::ValueVariant> propValues =
187                         propertyEntry.second->getAllowedValues();
188
189                     // TODO: Use RAML function once available
190                     if (0 < propertyEntry.second->getAllowedValuesSize())
191                     {
192                         std::vector<std::string> allowedValues;
193                         for (auto & propValue : propValues)
194                         {
195                             std::string value = boost::lexical_cast<std::string> (propValue);
196                             allowedValues.push_back(value);
197                         }
198                         repSchema->setAllowedValues(propertyEntry.second->getName(), allowedValues);
199                     }
200                 }
201                 break;
202         }
203     }
204
205     return repSchema;
206 }
207
208 RequestType RequestModelBuilder::getRequestType(RAML::ActionType actionType)
209 {
210     switch (actionType)
211     {
212         case RAML::ActionType::GET:
213             return RequestType::RQ_TYPE_GET;
214         case RAML::ActionType::PUT:
215             return RequestType::RQ_TYPE_PUT;
216         case RAML::ActionType::POST:
217             return RequestType::RQ_TYPE_POST;
218         case RAML::ActionType::DELETE:
219             return RequestType::RQ_TYPE_DELETE;
220     }
221 }
222