Imported Upstream version 0.9.2
[platform/upstream/iotivity.git] / service / soft-sensor-manager / SSMCore / src / QueryProcessor / CQLParser.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 #include "CQLParser.h"
21
22 Token::Token()
23 {
24     number = -1;
25     name = "";
26     type = Command;
27     condition = ModelCondition::PREDICATE_EQ;
28 }
29
30 std::vector<std::string> CCQLParser::tokenize(const std::string &input)
31 {
32     std::vector<std::string> temp;
33     temp.push_back(",");
34     temp.push_back(" ");
35
36     std::vector<std::string> tokens_temp;
37     std::string arrage_query = input;
38     arrage_query = check_Predicate(arrage_query);
39     for (unsigned int i = 0 ; i < temp.size(); i++)
40     {
41
42         tokens_temp.clear();
43         tokens_temp = getTokens(arrage_query, temp.at(i));
44         arrage_query = "";
45         for (unsigned int j = 0  ; j < tokens_temp.size() ; j++)
46         {
47             arrage_query += tokens_temp.at(j) + " ";
48             //cout << "element = " << tokens_temp.at(j) << endl;
49         }
50     }
51     return tokens_temp;
52 }
53
54 bool CCQLParser::parse(std::string input, Token *root)
55 {
56     std::vector<std::string> tokens = tokenize(input);
57     bool flag;//get,sub,if
58     bool value_flag = false;
59     bool isCondition = false;
60
61     for (unsigned int i = 0 ; i < tokens.size() ; i++)
62     {
63         if ( tolower(tokens.at(i)) == "get" || tolower(tokens.at(i)) == "subscribe"
64              || tolower(tokens.at(i)) == "if")
65         {
66             Token temp;
67
68             if (i != tokens.size() - 1 && tolower(tokens.at(i)) == "subscribe"
69                 && tolower(tokens.at(i + 1)) == "if")
70             {
71                 temp.type = Command;
72                 temp.name = tokens.at(i);
73                 root->child_token.push_back(temp);
74                 temp.name = tokens.at(i + 1);
75
76                 //Token temp1;
77                 //temp1.type = Command;
78                 //temp1.name = tokens.at(i+1);
79
80
81
82
83                 i++;
84                 //temp1 = temp;
85                 flag = false;
86                 isCondition = true;
87             }
88             else
89             {
90                 /*
91                 temp.type = Command;
92                 temp.name = tokens.at(i);
93                 root->child_token.push_back(temp);
94                 */
95                 temp.type = Command;
96                 temp.name = tokens.at(i);
97                 if (tokens.at(i) == "if")
98                 {
99                     flag = false;
100                     isCondition = true;
101                 }
102                 else
103                 {
104                     flag = true;
105                 }
106             }
107
108             SORT lastType = Command;
109             while (1)
110             {
111                 //int count = 0;
112                 i++;
113
114                 if (value_flag == true)
115                 {
116                     value_flag = false;
117                     lastType = Context;
118                     i++;
119                 }
120
121                 if ( i >= tokens.size() || tolower(tokens.at(i) ) == "if")
122                 {
123                     i--;
124                     break;
125                 }
126
127                 //enum condition {EQ,GTE,GT,LT,LTE,NEQ};
128                 Token temp1;
129                 temp1.name = tokens.at(i);
130
131
132                 if (tokens.at(i) == "=" || tokens.at(i) == "==")
133                 {
134                     temp1.condition = ModelCondition::PREDICATE_EQ;
135                     temp1.type = Condi;
136                     value_flag = true;
137
138                 }
139                 else if (tokens.at(i) == ">=")
140                 {
141                     temp1.condition = ModelCondition::PREDICATE_GTE;
142                     temp1.type = Condi;
143                     value_flag = true;
144                 }
145                 else if (tokens.at(i) == ">")
146                 {
147                     temp1.condition =  ModelCondition::PREDICATE_GT;
148                     temp1.type = Condi;
149                     value_flag = true;
150                 }
151                 else if (tokens.at(i) == "<")
152                 {
153                     temp1.condition = ModelCondition::PREDICATE_LT;
154                     temp1.type = Condi;
155                     value_flag = true;
156                 }
157                 else if (tokens.at(i) == "<=")
158                 {
159                     temp1.condition = ModelCondition::PREDICATE_LTE;
160                     temp1.type = Condi;
161                     value_flag = true;
162                 }
163                 else if (tokens.at(i) == "!=")
164                 {
165                     temp1.condition = ModelCondition::PREDICATE_NEQ;
166                     temp1.type = Condi;
167                     value_flag = true;
168                 }
169                 else
170                 {
171                     temp1.type = Context;
172
173                     //if current context token is reserved keyword, that return error
174                     if (tolower(tokens.at(i)) == "get" || tolower(tokens.at(i)) == "subscribe")
175                     {
176                         return false;
177                     }
178                 }
179
180                 if (flag == true)
181                 {
182
183                     if (tolower(tokens.at(i)) == "and" || tolower(tokens.at(i)) == "or")
184                     {
185                         temp1.type = And_or;
186                         flag = false;
187                     }
188
189                     if (split(tokens.at(i), &temp1, flag ) != true) //false -> Property
190                     {
191                         return false;
192                     }
193                 }
194                 else
195                 {
196                     //token count not matched, return and let grammer checker detects
197                     if (tokens.size() < i + 3)
198                     {
199                         return false;
200                     }
201
202                     if (split(tokens.at(i), &temp1, flag , tokens.at(i + 1),
203                               tokens.at(i + 2)) != true) //false -> Property
204                     {
205                         return false;
206                     }
207                     flag = true;
208                 }
209
210                 if (isCondition && lastType == temp1.type)
211                 {
212                     return false;
213                 }
214
215                 lastType = temp1.type;
216
217                 temp.child_token.push_back(temp1);
218             }
219             root->child_token.push_back(temp);
220         }
221     }
222
223     return true;
224 }
225
226 std::string CCQLParser::tolower(std::string str)
227 {
228     for (unsigned int i = 0 ; i < str.size() ; i++)
229     {
230         if (str[i] <= 'Z' && str[i] >= 'A')
231         {
232             str[i] += 32;
233         }
234     }
235
236     return str;
237 }
238
239 std::vector<std::string> CCQLParser::getTokens(const std::string &str,
240         const std::string &delimiters)
241 {
242     std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
243     std::string::size_type pos     = str.find_first_of(delimiters, lastPos);
244     std::vector<std::string> tokens;
245
246     while (std::string::npos != pos || std::string::npos != lastPos)
247     {
248         tokens.push_back(str.substr(lastPos, pos - lastPos));
249         lastPos = str.find_first_not_of(delimiters, pos);
250         pos = str.find_first_of(delimiters, lastPos);
251     }
252
253     if (tokens.size() == 0)
254         tokens.push_back("\"\"");
255
256     return tokens;
257 }
258
259 void CCQLParser::check_index(std::string input, Token *token)
260 {
261     std::vector<std::string> tokens = getTokens(input, "[");
262
263     if (tokens.size() == 2)
264     {
265         if (tolower(tokens.at(1)) == "all]")
266         {
267             token->name = tokens.at(0);
268             token->number = INDEX_ALL;
269
270         }
271         else if (tolower(tokens.at(1)) == "this]")
272         {
273             token->name = tokens.at(0);
274             token->number = INDEX_THIS;
275
276         }
277         else
278         {
279             int num = atoi(tokens.at(1).c_str());
280             token->name = tokens.at(0);
281             token->number = num;
282         }
283     }
284 }
285
286 bool CCQLParser::split(std::string input, Token *root, bool flag, std::string arg1,
287                        std::string arg2)
288 {
289     std::vector<std::string> tokens = getTokens(input, ".");
290     Token *temp_token = root;
291
292     for (unsigned int j = 0 ; j < tokens.size() ; j++)
293     {
294         if (j == 0 )
295         {
296             temp_token->name = tokens.at(j);
297             check_index(tokens.at(j), temp_token);
298         }
299         else
300         {
301             if (j == tokens.size() - 1 && flag == false)
302             {
303                 ModelProperty property;
304                 property.propertyName = tokens.at(j);
305
306                 if (arg2[0] == '\"')
307                 {
308                     std::vector<std::string> tokens_temp = getTokens(arg2, "\"");
309
310                     property.propertyValue = tokens_temp.at(0);
311                     property.propertyType = ModelProperty::TYPE_TEXT;
312
313                     temp_token->model_property = property;
314
315                     //root->child_token.push_back(temp1);
316                 }
317
318                 else
319                 {
320                     //temp1->number = atof(arg2.c_str());
321
322                     // 0 text /1 integer /2 real
323                     if (check_number(arg2) == TYPEINTEGER)
324                     {
325                         property.propertyType =  ModelProperty::TYPE_INTEGER;
326                     }
327                     else if (check_number(arg2) == TYPEREAL)
328                     {
329                         property.propertyType = ModelProperty::TYPE_REAL;
330                     }
331                     else
332                     {
333                         //unknown type raise error
334                         return false;
335                     }
336                     property.propertyValue = arg2;
337
338                     temp_token->model_property = property;
339                 }
340             }
341             else
342             {
343                 Token temp1;
344                 temp1.type = Context;
345                 temp1.name = tokens.at(j);
346                 check_index(tokens.at(j), &temp1);
347                 temp_token->child_token.push_back(temp1);
348                 temp_token = &(temp_token->child_token.back());
349             }
350         }
351     }
352
353     return true;
354 }
355
356 int CCQLParser::check_number(std::string &str)
357 {
358     int flag = 0; // 0 text /1 integer /2 real
359     int dotCount = 0;
360
361     std::string::const_iterator it = str.begin();
362     while (it != str.end())
363     {
364         if (*it == '.')
365         {
366             dotCount++;
367         }
368         else if (isdigit(*it) == false)
369         {
370             //this is text
371             dotCount = 2;
372             break;
373         }
374
375         ++it;
376     }
377
378     if (dotCount == 0)
379     {
380         flag = 1;
381     }
382     else if (dotCount == 1)
383     {
384         flag = 2;
385     }
386
387     return flag;
388 }
389
390 std::string CCQLParser::check_Predicate(std::string input)
391 {
392     std::string temp = "";
393     for (unsigned int i = 0 ; i < input.size() ; i++)
394     {
395         if (i == 0)
396         {
397             temp += input[0];
398             continue;
399         }
400
401         switch (input[i])
402         {
403             case '=':
404                 if (input[i - 1] != '=' && input[i - 1] != '!' && input[i - 1] != '>' && input[i - 1] != '<'
405                     && input[i - 1] != ' ')
406                 {
407                     temp += ' ';
408                 }
409                 temp += input[i];
410                 break;
411             case '!':
412             case '<':
413             case '>':
414                 if (input[i - 1] != ' ')
415                 {
416                     temp += ' ';
417                 }
418                 temp += input[i];
419                 break;
420             case ' ':
421                 temp += input[i];
422                 break;
423             default:
424                 if (input[i - 1] == '=' || input[i - 1] == '<' || input[i - 1] == '>')
425                 {
426                     temp += ' ';
427                 }
428                 temp += input[i];
429                 break;
430         }
431     }
432
433     return temp;
434 }
435
436 bool CCQLParser::check_grammer(Token *token)
437 {
438     if (token->child_token.size() == 1 && tolower(token->child_token.at(0).name) == "get")
439     {
440         if (token->child_token.at(0).child_token.size() > 0)
441         {
442             return true;
443         }
444         else
445         {
446             return false;
447         }
448
449     }
450     else if (token->child_token.size() == 2)
451     {
452         if (token->child_token.at(1).child_token.size() > 0)
453         {
454             if (tolower(token->child_token.at(0).name) == "subscribe")
455             {
456                 return true;
457             }
458             else if (tolower(token->child_token.at(0).name) == "get")
459             {
460                 if (token->child_token.at(0).child_token.size() > 0)
461                 {
462                     return true;
463                 }
464                 else
465                 {
466                     return false;
467                 }
468             }
469             else
470             {
471                 return false;
472             }
473
474         }
475         else
476         {
477             return false;
478         }
479     }
480     else
481     {
482         return false;
483     }
484 }