1 /******************************************************************
\r
3 * Copyright 2015 Samsung Electronics All Rights Reserved.
\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
11 * http://www.apache.org/licenses/LICENSE-2.0
\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
19 ******************************************************************/
\r
21 #include "JsonSchema.h"
\r
22 using namespace std;
\r
27 void JsonSchema::readJson()
\r
32 cJSON *jsonId = cJSON_GetObjectItem(m_cjson, "id");
\r
35 m_id = jsonId->valuestring;
\r
37 cJSON *jsonSchema = cJSON_GetObjectItem(m_cjson, "$schema");
\r
40 m_schema = jsonSchema->valuestring;
\r
42 cJSON *jsonTitle = cJSON_GetObjectItem(m_cjson, "title");
\r
45 m_title = jsonTitle->valuestring;
\r
47 cJSON *jsonType = cJSON_GetObjectItem(m_cjson, "type");
\r
50 m_type = jsonType->valuestring;
\r
52 cJSON *jsonDescription = cJSON_GetObjectItem(m_cjson, "description");
\r
53 if (jsonDescription)
\r
55 m_description = jsonDescription->valuestring;
\r
57 cJSON *jsonDefinitions = cJSON_GetObjectItem(m_cjson, "definitions");
\r
58 if (jsonDefinitions)
\r
60 cJSON *childDefinitions = jsonDefinitions->child;
\r
61 while (childDefinitions)
\r
63 std::string defName = childDefinitions->string;
\r
64 addDefinition(defName, readDef(childDefinitions, defName));
\r
65 childDefinitions = childDefinitions->next;
\r
68 cJSON *jsonProperties = cJSON_GetObjectItem(m_cjson, "properties");
\r
71 cJSON *childProperties = jsonProperties->child;
\r
72 while (childProperties)
\r
74 std::string attName = childProperties->string;
\r
75 addProperty(attName, readProp(childProperties, attName));
\r
76 childProperties = childProperties->next;
\r
79 if (m_type == "array")
\r
81 cJSON *jsonItems = cJSON_GetObjectItem(m_cjson, "items");
\r
84 if (jsonItems->type == 5)
\r
86 int item_size = cJSON_GetArraySize(jsonItems);
\r
90 cJSON *item = cJSON_GetArrayItem(jsonItems, item_index);
\r
91 Items *newItem = readItems(item);
\r
94 while ( ++item_index < item_size);
\r
98 Items *newItem = readItems(jsonItems);
\r
103 cJSON *jsonAdditionalProperties = cJSON_GetObjectItem(m_cjson, "additionalProperties");
\r
104 if (jsonAdditionalProperties)
\r
105 m_additionalProperties = jsonAdditionalProperties->type;
\r
107 m_additionalProperties = cJSON_True;
\r
109 cJSON *jsonReference = cJSON_GetObjectItem(m_cjson, "$ref");
\r
112 readJsonRef(jsonReference);
\r
114 cJSON *jsonAllOf = cJSON_GetObjectItem(m_cjson, "allOf");
\r
117 readAllOf(jsonAllOf);
\r
119 cJSON *jsonRequiredValues = cJSON_GetObjectItem(m_cjson, "required");
\r
120 if (jsonRequiredValues)
\r
122 int size = cJSON_GetArraySize(jsonRequiredValues);
\r
126 setRequiredValue(cJSON_GetArrayItem(jsonRequiredValues, index)->valuestring);
\r
128 while ( ++index < size);
\r
132 Definitions *JsonSchema::readDef(cJSON *childDefinitions, const std::string &defName)
\r
134 Definitions *definition = new Definitions(defName);
\r
136 cJSON *defType = cJSON_GetObjectItem(childDefinitions, "type");
\r
139 std::string type = defType->valuestring;
\r
140 definition->setType(type);
\r
142 cJSON *defProperties = cJSON_GetObjectItem(childDefinitions, "properties");
\r
145 cJSON *childProperties = defProperties->child;
\r
146 while (childProperties)
\r
148 std::string attName = childProperties->string;
\r
149 definition->addProperty(attName, readProp(childProperties, attName));
\r
150 childProperties = childProperties->next;
\r
153 cJSON *defRequiredValues = cJSON_GetObjectItem(childDefinitions, "required");
\r
154 if (defRequiredValues)
\r
156 int size = cJSON_GetArraySize(defRequiredValues);
\r
160 definition->setRequiredValue(cJSON_GetArrayItem(defRequiredValues, index)->valuestring);
\r
162 while ( ++index < size);
\r
164 cJSON *defReference = cJSON_GetObjectItem(childDefinitions, "$ref");
\r
167 readDefRef(defReference, definition);
\r
169 cJSON *defAllOf = cJSON_GetObjectItem(childDefinitions, "allOf");
\r
172 readDefAllOf(defAllOf, definition);
\r
177 Properties *JsonSchema::readProp(cJSON *childProperties, const std::string &attName )
\r
179 Properties *property = new Properties(attName);
\r
181 cJSON *propertyUpdateFrequency = cJSON_GetObjectItem(childProperties, "update_frequency");
\r
182 if (propertyUpdateFrequency)
\r
184 property->setUpdateFrequencyTime(propertyUpdateFrequency->valueint);
\r
186 cJSON *propertyDescription = cJSON_GetObjectItem(childProperties, "description");
\r
187 if (propertyDescription)
\r
189 property->setDescription(propertyDescription->valuestring);
\r
191 cJSON *propertyType = cJSON_GetObjectItem(childProperties, "type");
\r
194 std::string attType;
\r
195 if (propertyType->type == 4)
\r
197 attType = propertyType->valuestring;
\r
198 property->setType(attType);
\r
200 else if (propertyType->type == 5)
\r
202 attType = cJSON_GetArrayItem(propertyType, 0)->valuestring;
\r
203 property->setType(attType);
\r
205 readValues(childProperties, property, attType);
\r
207 cJSON *defaultValue = cJSON_GetObjectItem(childProperties, "default");
\r
210 if (defaultValue->type == 4)
\r
212 property->setValue((std::string)defaultValue->valuestring);
\r
214 else if (defaultValue->type == 3)
\r
216 if (property->getType() == "number")
\r
217 property->setValue((double)defaultValue->valuedouble);
\r
219 property->setValue((int)defaultValue->valueint );
\r
221 else if (defaultValue->type == 1)
\r
223 property->setValue((bool)true);
\r
225 else if (defaultValue->type == 0)
\r
227 property->setValue((bool)false);
\r
231 cJSON *allowedvalues = cJSON_GetObjectItem(childProperties, "enum");
\r
234 if ((cJSON_GetArrayItem(allowedvalues, 0)->type) == 4)
\r
236 int size = cJSON_GetArraySize(allowedvalues);
\r
238 std::vector<std::string> allwdValues;
\r
241 allwdValues.push_back(cJSON_GetArrayItem(allowedvalues, idx)->valuestring);
\r
243 while ( ++idx < size);
\r
244 property->setAllowedValues(allwdValues);
\r
246 else if ((cJSON_GetArrayItem(allowedvalues, 0)->type) == 3)
\r
248 int size = cJSON_GetArraySize(allowedvalues);
\r
250 if (property->getType() == "number")
\r
252 std::vector<double> allwdValues;
\r
255 allwdValues.push_back(cJSON_GetArrayItem(allowedvalues, idx)->valuedouble);
\r
257 while ( ++idx < size);
\r
258 property->setAllowedValues(allwdValues);
\r
262 std::vector<int> allwdValues;
\r
265 allwdValues.push_back(cJSON_GetArrayItem(allowedvalues, idx)->valueint);
\r
267 while ( ++idx < size);
\r
268 property->setAllowedValues(allwdValues);
\r
271 else if (((cJSON_GetArrayItem(allowedvalues, 0)->type) == 1)
\r
272 || ((cJSON_GetArrayItem(allowedvalues, 0)->type) == 0))
\r
274 int size = cJSON_GetArraySize(allowedvalues);
\r
276 std::vector<bool> allwdValues;
\r
279 if (cJSON_GetArrayItem(allowedvalues, idx)->type)
\r
280 allwdValues.push_back(true);
\r
282 allwdValues.push_back(false);
\r
284 while ( ++idx < size);
\r
285 property->setAllowedValues(allwdValues);
\r
291 void JsonSchema::readValues(cJSON *childProperties, Properties *property ,
\r
292 const std::string &attType)
\r
294 if (attType == "string")
\r
296 readString(childProperties, property);
\r
298 else if (attType == "integer")
\r
300 readNumber(childProperties, property);
\r
302 else if (attType == "array")
\r
304 readArray(childProperties, property);
\r
306 else if (attType == "number")
\r
308 readNumber(childProperties, property);
\r
312 void JsonSchema::readString(cJSON *childProperties, Properties *property)
\r
314 cJSON *stringMax = cJSON_GetObjectItem(childProperties, "maxLength");
\r
317 cJSON *exclusiveMax = cJSON_GetObjectItem(childProperties, "exclusiveMaximum");
\r
320 if (exclusiveMax->type == cJSON_True)
\r
321 property->setMax (--(stringMax->valueint));
\r
323 property->setMax(stringMax->valueint);
\r
326 property->setMax(stringMax->valueint);
\r
328 cJSON *stringMin = cJSON_GetObjectItem(childProperties, "minLength");
\r
331 cJSON *exclusiveMin = cJSON_GetObjectItem(childProperties, "exclusiveMinimum");
\r
334 if (exclusiveMin->type == cJSON_True)
\r
335 property->setMin( ++(stringMin->valueint));
\r
337 property->setMin(stringMin->valueint);
\r
340 property->setMin(stringMin->valueint);
\r
342 cJSON *stringFormat = cJSON_GetObjectItem(childProperties, "format");
\r
345 property->setFormat(stringFormat->valuestring);
\r
347 cJSON *stringPattern = cJSON_GetObjectItem(childProperties, "pattern");
\r
350 property->setPattern(stringPattern->valuestring);
\r
354 void JsonSchema::readArray(cJSON *childProperties, Properties *property)
\r
356 cJSON *itemValues = cJSON_GetObjectItem(childProperties, "items");
\r
359 if (itemValues->type == 5)
\r
361 int item_size = cJSON_GetArraySize(itemValues);
\r
362 int item_index = 0;
\r
365 cJSON *item = cJSON_GetArrayItem(itemValues, item_index);
\r
366 Items *newItem = readItems(item);
\r
367 property->setItem(newItem);
\r
369 while ( ++item_index < item_size);
\r
373 Items *newItem = readItems(itemValues);
\r
374 property->setItem(newItem);
\r
377 cJSON *itemsMax = cJSON_GetObjectItem(childProperties, "maxItems");
\r
380 cJSON *exclusiveMax = cJSON_GetObjectItem(childProperties, "exclusiveMaximum");
\r
383 if (exclusiveMax->type == cJSON_True)
\r
384 property->setMax( --(itemsMax->valueint));
\r
386 property->setMax(itemsMax->valueint);
\r
389 property->setMax(itemsMax->valueint);
\r
391 cJSON *itemsMin = cJSON_GetObjectItem(childProperties, "minLength");
\r
394 cJSON *exclusiveMin = cJSON_GetObjectItem(childProperties, "exclusiveMinimum");
\r
397 if (exclusiveMin->type == cJSON_True)
\r
398 property->setMin( ++(itemsMin->valueint));
\r
400 property->setMin(itemsMin->valueint);
\r
403 property->setMin(itemsMin->valueint);
\r
405 cJSON *uniqueItems = cJSON_GetObjectItem(childProperties, "uniqueItems");
\r
408 property->setUnique(uniqueItems->type);
\r
412 property->setUnique(cJSON_True);
\r
414 cJSON *additionalItems = cJSON_GetObjectItem(childProperties, "additionalItems");
\r
415 if (additionalItems)
\r
417 property->setAdditionalItems(additionalItems->type);
\r
421 property->setAdditionalItems(cJSON_True);
\r
425 void JsonSchema::readNumber(cJSON *childProperties, Properties *property)
\r
427 cJSON *Max = cJSON_GetObjectItem(childProperties, "maximum");
\r
430 cJSON *exclusiveMax = cJSON_GetObjectItem(childProperties, "exclusiveMaximum");
\r
433 if (exclusiveMax->type == cJSON_True)
\r
434 property->setMax( --(Max->valueint));
\r
436 property->setMax(Max->valueint);
\r
439 property->setMax(Max->valueint);
\r
441 cJSON *Min = cJSON_GetObjectItem(childProperties, "minimum");
\r
444 cJSON *exclusiveMin = cJSON_GetObjectItem(childProperties, "exclusiveMinimum");
\r
447 if (exclusiveMin->type == cJSON_True)
\r
448 property->setMin( ++(Min->valueint));
\r
450 property->setMin(Min->valueint);
\r
453 property->setMin(Min->valueint);
\r
455 cJSON *multipleOf = cJSON_GetObjectItem(childProperties, "multipleOf");
\r
458 property->setMultipleOf(multipleOf->valueint);
\r
462 Definitions *JsonSchema::readRef(std::string m_ref)
\r
464 std::string delimiter1 = "#";
\r
465 std::string delimiter2 = "/";
\r
466 std::string fileName;
\r
467 if (! m_ref.empty())
\r
469 std::size_t pos = m_ref.find(delimiter1);
\r
470 if ( (pos = m_ref.find(delimiter1)) != std::string::npos)
\r
472 fileName = m_ref.substr(0, pos);
\r
473 m_ref.erase(0, pos);
\r
475 m_ref.erase(0, delimiter1 .length());
\r
476 std::string defName;
\r
478 if (! m_ref.empty())
\r
480 m_ref.erase(0, delimiter2 .length());
\r
481 std::string keyName;
\r
482 if ( (pos = m_ref.find(delimiter2)) != std::string::npos)
\r
484 keyName = m_ref.substr(0, pos);
\r
485 m_ref.erase(0, pos + delimiter2.length());
\r
486 if (keyName == "definitions")
\r
488 if ( (pos = m_ref.find(delimiter2)) != std::string::npos)
\r
490 defName = m_ref.substr(0, pos);
\r
492 else if (! m_ref.empty())
\r
499 if (!fileName.empty())
\r
501 if (!(defName.empty()))
\r
503 cJSON *m_json = m_includeResolver->readToJson(fileName);
\r
504 JsonSchema *Refparser = new JsonSchema(m_json, m_includeResolver);
\r
505 Definitions *definition = Refparser->getDefinition(defName);
\r
506 if (definition == nullptr)
\r
507 throw JsonException("Definition Name Incorrect");
\r
513 if (!(defName.empty()))
\r
515 if (getDefinition(defName) == nullptr)
\r
516 throw JsonException("Definition Name Incorrect");
\r
517 return getDefinition(defName);
\r
522 void JsonSchema::readAllOf(cJSON *allofValues)
\r
524 int size = cJSON_GetArraySize(allofValues);
\r
528 cJSON *childAllOf = cJSON_GetArrayItem(allofValues, index);
\r
529 cJSON *jsonReference = cJSON_GetObjectItem(childAllOf, "$ref");
\r
532 readJsonRef(jsonReference );
\r
534 cJSON *jsonRequiredValues = cJSON_GetObjectItem(childAllOf, "required");
\r
535 if (jsonRequiredValues)
\r
537 int len = cJSON_GetArraySize(jsonRequiredValues);
\r
541 setRequiredValue(cJSON_GetArrayItem(jsonRequiredValues, idx)->valuestring);
\r
543 while ( ++idx < len);
\r
546 while ( ++index < size);
\r
548 void JsonSchema::readJsonRef(cJSON *jsonReference)
\r
550 std::string m_ref = jsonReference->valuestring;
\r
551 std::map<std::string, Properties *> properties;
\r
552 std::vector<std::string> required;
\r
554 std::string web = "http://";
\r
555 std::string delimiter = "#";
\r
556 std::size_t pos = m_ref.find(web);
\r
558 if (pos == std::string::npos) // If Web Link Is GIVEN TO READ
\r
560 pos = m_ref.find(delimiter);
\r
561 if ( pos == (m_ref.length() - 1) )
\r
563 std::string fileName = m_ref.substr(0, pos);
\r
564 cJSON *m_json = m_includeResolver->readToJson(fileName);
\r
565 JsonSchema *Refparser = new JsonSchema(m_json, m_includeResolver);
\r
567 properties = Refparser->getProperties();
\r
568 required = Refparser->getRequiredValues();
\r
572 Definitions *definition = readRef(m_ref);
\r
573 properties = definition->getProperties();
\r
574 required = definition->getRequiredValues();
\r
576 for ( auto it : properties)
\r
578 std:: string name = it.first;
\r
579 addProperty(name, it.second);
\r
581 for (auto it : required )
\r
583 setRequiredValue(it);
\r
588 void JsonSchema::readDefAllOf(cJSON *allofValues, Definitions *definition)
\r
590 int size = cJSON_GetArraySize(allofValues);
\r
594 cJSON *childAllOf = cJSON_GetArrayItem(allofValues, index);
\r
595 cJSON *defReference = cJSON_GetObjectItem(childAllOf, "$ref");
\r
598 readDefRef(defReference , definition);
\r
600 cJSON *defRequiredValues = cJSON_GetObjectItem(allofValues, "required");
\r
601 if (defRequiredValues)
\r
603 int len = cJSON_GetArraySize(defRequiredValues);
\r
607 definition->setRequiredValue(cJSON_GetArrayItem(defRequiredValues, idx)->valuestring);
\r
609 while ( ++idx < len);
\r
612 while ( ++index < size);
\r
614 void JsonSchema::readDefRef(cJSON *defReference, Definitions *definition)
\r
616 std::string m_ref = defReference->valuestring;
\r
617 std::map<std::string, Properties *> properties;
\r
618 std::vector<std::string> required;
\r
621 std::string web = "http://";
\r
622 std::string delimiter = "#";
\r
623 std::size_t pos = m_ref.find(web);
\r
625 if (pos == std::string::npos) // If Web Link Is GIVEN TO READ
\r
627 pos = m_ref.find(delimiter);
\r
628 if ( pos == (m_ref.length() - 1) )
\r
630 std::string fileName = m_ref.substr(0, pos);
\r
631 cJSON *m_json = m_includeResolver->readToJson(fileName);
\r
632 JsonSchema *Refparser = new JsonSchema(m_json, m_includeResolver);
\r
634 properties = Refparser->getProperties();
\r
635 required = Refparser->getRequiredValues();
\r
636 type = Refparser->getType();
\r
640 Definitions *definitionRef = readRef(m_ref);
\r
641 properties = definitionRef->getProperties();
\r
642 required = definitionRef->getRequiredValues();
\r
643 type = definitionRef->getType();
\r
645 for (auto it : properties)
\r
647 definition->addProperty(it.first, it.second);
\r
649 for ( auto it : required)
\r
651 definition->setRequiredValue(it);
\r
653 definition->setType(type);
\r
656 Items *JsonSchema::readItems(cJSON *item)
\r
658 Items *newItem = new Items();
\r
659 cJSON *itemType = cJSON_GetObjectItem(item, "type");
\r
662 std::string type = itemType->valuestring;
\r
663 newItem->setType(type);
\r
666 cJSON *itemProperties = cJSON_GetObjectItem(item, "properties");
\r
667 if (itemProperties)
\r
669 cJSON *childProperties = itemProperties->child;
\r
670 while (childProperties)
\r
672 std::string attName = childProperties->string;
\r
673 Properties *property = readProp(childProperties, attName);
\r
675 newItem->addProperty(attName, property);
\r
676 childProperties = childProperties->next;
\r
680 cJSON *allowedvalues = cJSON_GetObjectItem(item, "enum");
\r
683 if ((cJSON_GetArrayItem(allowedvalues, 0)->type) == 4)
\r
685 int size = cJSON_GetArraySize(allowedvalues);
\r
687 std::vector<std::string> allwdValues;
\r
690 allwdValues.push_back(cJSON_GetArrayItem(allowedvalues, idx)->valuestring);
\r
692 while ( ++idx < size);
\r
693 newItem->setAllowedValues(allwdValues);
\r
695 else if ((cJSON_GetArrayItem(allowedvalues, 0)->type) == 3)
\r
697 int size = cJSON_GetArraySize(allowedvalues);
\r
699 if (newItem->getType() == "number")
\r
701 std::vector<double> allwdValues;
\r
704 allwdValues.push_back(cJSON_GetArrayItem(allowedvalues, idx)->valuedouble);
\r
706 while ( ++idx < size);
\r
707 newItem->setAllowedValues(allwdValues);
\r
711 std::vector<int> allwdValues;
\r
714 allwdValues.push_back(cJSON_GetArrayItem(allowedvalues, idx)->valueint);
\r
716 while ( ++idx < size);
\r
717 newItem->setAllowedValues(allwdValues);
\r
720 else if (((cJSON_GetArrayItem(allowedvalues, 0)->type) == 1)
\r
721 || ((cJSON_GetArrayItem(allowedvalues, 0)->type) == 0))
\r
723 int size = cJSON_GetArraySize(allowedvalues);
\r
725 std::vector<bool> allwdValues;
\r
728 if (cJSON_GetArrayItem(allowedvalues, idx)->type)
\r
729 allwdValues.push_back(true);
\r
731 allwdValues.push_back(false);
\r
733 while ( ++idx < size);
\r
734 newItem->setAllowedValues(allwdValues);
\r
737 cJSON *itemRequiredValues = cJSON_GetObjectItem(item, "required");
\r
738 if (itemRequiredValues)
\r
740 int size = cJSON_GetArraySize(itemRequiredValues);
\r
744 newItem->setRequiredValue(cJSON_GetArrayItem(itemRequiredValues, index)->valuestring);
\r
746 while ( ++index < size);
\r
748 cJSON *itemReference = cJSON_GetObjectItem(item, "$ref");
\r
751 readItemRef(itemReference , newItem);
\r
753 cJSON *itemAllOf = cJSON_GetObjectItem(item, "allOf");
\r
756 readItemAllOf(itemAllOf , newItem);
\r
761 void JsonSchema::readItemRef(cJSON *itemReference, Items *item)
\r
763 std::string m_ref = itemReference->valuestring;
\r
764 std::map<std::string, Properties *> properties;
\r
765 std::vector<std::string> required;
\r
768 std::string web = "http://";
\r
769 std::string delimiter = "#";
\r
770 std::size_t pos = m_ref.find(web);
\r
772 if (pos == std::string::npos) // If Web Link Is GIVEN TO READ
\r
774 pos = m_ref.find(delimiter);
\r
775 if ( pos == (m_ref.length() - 1 ) )
\r
777 std::string fileName = m_ref.substr(0, pos);
\r
778 cJSON *m_json = m_includeResolver->readToJson(fileName);
\r
779 JsonSchema *Refparser = new JsonSchema(m_json, m_includeResolver);
\r
781 properties = Refparser->getProperties();
\r
782 required = Refparser->getRequiredValues();
\r
783 type = Refparser->getType();
\r
787 Definitions *definitionRef = readRef(m_ref);
\r
788 properties = definitionRef->getProperties();
\r
789 required = definitionRef->getRequiredValues();
\r
790 type = definitionRef->getType();
\r
792 for ( auto it : properties)
\r
794 std:: string name = it.first;
\r
795 item->addProperty(name, it.second);
\r
797 for ( auto it : required)
\r
799 item->setRequiredValue(it);
\r
801 item->setType(type);
\r
805 void JsonSchema::readItemAllOf(cJSON *allofValues, Items *item)
\r
807 int size = cJSON_GetArraySize(allofValues);
\r
811 cJSON *childAllOf = cJSON_GetArrayItem(allofValues, index);
\r
812 cJSON *itemReference = cJSON_GetObjectItem(childAllOf, "$ref");
\r
815 readItemRef(itemReference, item);
\r
817 cJSON *itemRequiredValues = cJSON_GetObjectItem(allofValues, "required");
\r
818 if (itemRequiredValues)
\r
820 int len = cJSON_GetArraySize(itemRequiredValues);
\r
824 item->setRequiredValue(cJSON_GetArrayItem(itemRequiredValues, idx)->valuestring);
\r
826 while ( ++idx < len);
\r
829 while ( ++index < size);
\r