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