ctkMTDataParser.cpp 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623
  1. /*=============================================================================
  2. Library: CTK
  3. Copyright (c) German Cancer Research Center,
  4. Division of Medical and Biological Informatics
  5. Licensed under the Apache License, Version 2.0 (the "License");
  6. you may not use this file except in compliance with the License.
  7. You may obtain a copy of the License at
  8. http://www.apache.org/licenses/LICENSE-2.0
  9. Unless required by applicable law or agreed to in writing, software
  10. distributed under the License is distributed on an "AS IS" BASIS,
  11. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. See the License for the specific language governing permissions and
  13. limitations under the License.
  14. =============================================================================*/
  15. #include "ctkMTDataParser_p.h"
  16. #include "ctkAttributeDefinitionImpl_p.h"
  17. #include "ctkMTMsg_p.h"
  18. #include <service/log/ctkLogService.h>
  19. #include <QCoreApplication>
  20. #include <QDebug>
  21. const QString ctkMTDataParser::METADATA = "MetaData";
  22. const QString ctkMTDataParser::LOCALIZATION = "localization";
  23. const QString ctkMTDataParser::CONTEXT = "context";
  24. const QString ctkMTDataParser::OCD = "OCD";
  25. const QString ctkMTDataParser::ICON = "Icon";
  26. const QString ctkMTDataParser::AD = "AD";
  27. const QString ctkMTDataParser::CARDINALITY = "cardinality";
  28. const QString ctkMTDataParser::OPTION = "Option";
  29. const QString ctkMTDataParser::LABEL = "label";
  30. const QString ctkMTDataParser::VALUE = "value";
  31. const QString ctkMTDataParser::MIN = "min";
  32. const QString ctkMTDataParser::MAX = "max";
  33. const QString ctkMTDataParser::TYPE = "type";
  34. const QString ctkMTDataParser::SIZE = "size";
  35. const QString ctkMTDataParser::ID = "id";
  36. const QString ctkMTDataParser::NAME = "name";
  37. const QString ctkMTDataParser::DESCRIPTION = "description";
  38. const QString ctkMTDataParser::RESOURCE = "resource";
  39. const QString ctkMTDataParser::PID = "pid";
  40. const QString ctkMTDataParser::DEFAULT = "default";
  41. const QString ctkMTDataParser::ADREF = "adref";
  42. const QString ctkMTDataParser::CONTENT = "content";
  43. const QString ctkMTDataParser::FACTORY = "factoryPid";
  44. const QString ctkMTDataParser::PLUGIN = "plugin";
  45. const QString ctkMTDataParser::OPTIONAL = "optional";
  46. const QString ctkMTDataParser::OBJECT = "Object";
  47. const QString ctkMTDataParser::OCDREF = "ocdref";
  48. const QString ctkMTDataParser::ATTRIBUTE = "Attribute";
  49. const QString ctkMTDataParser::DESIGNATE = "Designate";
  50. const QString ctkMTDataParser::MERGE = "merge";
  51. const QString ctkMTDataParser::REQUIRED = "required";
  52. const QString ctkMTDataParser::INTEGER = "Integer";
  53. const QString ctkMTDataParser::STRING = "String";
  54. const QString ctkMTDataParser::DOUBLE = "Double";
  55. const QString ctkMTDataParser::LONG = "Long";
  56. const QString ctkMTDataParser::CHAR = "Char";
  57. const QString ctkMTDataParser::BOOLEAN = "Boolean";
  58. const QString ctkMTDataParser::PASSWORD = "Password";
  59. ctkMTDataParser::ctkMTDataParser(const QSharedPointer<ctkPlugin>& plugin, QIODevice* device, ctkLogService* logger)
  60. : _dp_plugin(plugin), _dp_xmlReader(device), logger(logger)
  61. {
  62. }
  63. QHash<QString, ctkObjectClassDefinitionImplPtr> ctkMTDataParser::doParse()
  64. {
  65. CTK_DEBUG(logger) << "Starting to parse metadata";
  66. while (_dp_xmlReader.readNextStartElement())
  67. {
  68. QStringRef name = _dp_xmlReader.name();
  69. if (name.compare(METADATA, Qt::CaseInsensitive) == 0)
  70. {
  71. metaDataHandler();
  72. }
  73. else
  74. {
  75. CTK_WARN(logger) << QCoreApplication::translate(ctkMTMsg::CONTEXT, ctkMTMsg::UNEXPECTED_ELEMENT).arg(name.toString());
  76. _dp_xmlReader.skipCurrentElement();
  77. }
  78. }
  79. if (_dp_xmlReader.hasError() &&
  80. !(_dp_xmlReader.atEnd() && _dp_xmlReader.error() == QXmlStreamReader::PrematureEndOfDocumentError))
  81. {
  82. errorHandler();
  83. return QHash<QString, ctkObjectClassDefinitionImplPtr>();
  84. }
  85. return _dp_pid_to_OCDs;
  86. }
  87. void ctkMTDataParser::metaDataHandler()
  88. {
  89. Q_ASSERT(_dp_xmlReader.isStartElement() && _dp_xmlReader.name().compare(METADATA, Qt::CaseInsensitive) == 0);
  90. QXmlStreamAttributes attributes = _dp_xmlReader.attributes();
  91. _dp_localization = attributes.value(LOCALIZATION).toString();
  92. _dp_context = attributes.value(CONTEXT).toString();
  93. // The variables "_dp_localization" and "_dp_context" will be used within
  94. // ocdHandler() and attributeDefinitionHandler() later.
  95. _dp_xmlReader.readNext();
  96. while(!_dp_xmlReader.hasError() && _dp_xmlReader.readNextStartElement())
  97. {
  98. QStringRef name = _dp_xmlReader.name();
  99. if (name.compare(DESIGNATE, Qt::CaseInsensitive) == 0)
  100. {
  101. designateHandler();
  102. }
  103. else if (name.compare(OCD, Qt::CaseInsensitive) == 0)
  104. {
  105. ocdHandler();
  106. }
  107. else
  108. {
  109. CTK_WARN(logger) << QCoreApplication::translate(ctkMTMsg::CONTEXT, ctkMTMsg::UNEXPECTED_ELEMENT).arg(name.toString());
  110. _dp_xmlReader.skipCurrentElement();
  111. }
  112. }
  113. if (_dp_xmlReader.hasError()) return;
  114. if (_dp_designateInfos.isEmpty())
  115. {
  116. // Schema defines at least one DESIGNATE is required.
  117. QString msg = QCoreApplication::translate(ctkMTMsg::CONTEXT, ctkMTMsg::MISSING_ELEMENT).arg(DESIGNATE);
  118. _dp_xmlReader.raiseError(msg);
  119. return;
  120. }
  121. for (int i = 0; i < _dp_designateInfos.size(); ++i)
  122. {
  123. const DesignateInfo& designateInfo = _dp_designateInfos[i];
  124. ctkObjectClassDefinitionImplPtr ocd = _dp_OCDs.value(designateInfo._ocdref);
  125. if (ocd)
  126. {
  127. if (designateInfo._factory_val.isEmpty())
  128. {
  129. ocd->setType(ctkObjectClassDefinitionImpl::PID);
  130. _dp_pid_to_OCDs.insert(designateInfo._pid_val, ocd);
  131. }
  132. else
  133. {
  134. ocd->setType(ctkObjectClassDefinitionImpl::FPID);
  135. _dp_pid_to_OCDs.insert(designateInfo._factory_val, ocd);
  136. }
  137. }
  138. else
  139. {
  140. QString msg = QCoreApplication::translate(ctkMTMsg::CONTEXT, ctkMTMsg::OCD_ID_NOT_FOUND).arg(designateInfo._ocdref);
  141. _dp_xmlReader.raiseError(msg);
  142. return;
  143. }
  144. }
  145. }
  146. void ctkMTDataParser::designateHandler()
  147. {
  148. Q_ASSERT(_dp_xmlReader.isStartElement() && _dp_xmlReader.name().compare(DESIGNATE, Qt::CaseInsensitive) == 0);
  149. DesignateInfo info;
  150. QXmlStreamAttributes atts = _dp_xmlReader.attributes();
  151. info._pid_val = atts.value(PID).toString();
  152. if (info._pid_val.isNull())
  153. {
  154. QString msg = QCoreApplication::translate(ctkMTMsg::CONTEXT, ctkMTMsg::MISSING_ATTRIBUTE).arg(PID).arg(_dp_xmlReader.name().toString());
  155. _dp_xmlReader.raiseError(msg);
  156. return;
  157. }
  158. info._factory_val = atts.value(FACTORY).toString();
  159. info._plugin_val = atts.value(PLUGIN).toString();
  160. if (info._plugin_val.isNull())
  161. {
  162. // Not a problem because PLUGIN is an optional attribute.
  163. }
  164. QString optional_str = atts.value(OPTIONAL).toString();
  165. if (optional_str.isNull())
  166. {
  167. // Not a problem, because OPTIONAL is an optional attribute.
  168. // The default value is "false".
  169. info._optional_val = false;
  170. }
  171. else
  172. {
  173. info._optional_val = toBool(optional_str);
  174. }
  175. QString merge_str = atts.value(MERGE).toString();
  176. if (merge_str.isNull())
  177. {
  178. // Not a problem, because MERGE is an optional attribute.
  179. // The default value is "false".
  180. info._merge_val = false;
  181. }
  182. else
  183. {
  184. info._merge_val = toBool(merge_str);
  185. }
  186. while (!_dp_xmlReader.hasError() && _dp_xmlReader.readNextStartElement())
  187. {
  188. QStringRef name = _dp_xmlReader.name();
  189. if (name.compare(OBJECT, Qt::CaseInsensitive) == 0)
  190. {
  191. objectHandler(info);
  192. }
  193. else
  194. {
  195. CTK_WARN(logger) << QCoreApplication::translate(ctkMTMsg::CONTEXT, ctkMTMsg::UNEXPECTED_ELEMENT).arg(name.toString());
  196. _dp_xmlReader.skipCurrentElement();
  197. }
  198. }
  199. if (_dp_xmlReader.hasError()) return;
  200. if (info._ocdref.isEmpty())
  201. {
  202. // Schema defines at least one OBJECT is required.
  203. QString msg = QCoreApplication::translate(ctkMTMsg::CONTEXT, ctkMTMsg::MISSING_ELEMENT).arg(OBJECT).arg(info._pid_val);
  204. _dp_xmlReader.raiseError(msg);
  205. return;
  206. }
  207. _dp_designateInfos.push_back(info);
  208. }
  209. void ctkMTDataParser::ocdHandler()
  210. {
  211. Q_ASSERT(_dp_xmlReader.isStartElement() && _dp_xmlReader.name().compare(OCD, Qt::CaseInsensitive) == 0);
  212. QStringRef name = _dp_xmlReader.name();
  213. QXmlStreamAttributes atts = _dp_xmlReader.attributes();
  214. QString ocd_name_val = atts.value(NAME).toString();
  215. if (ocd_name_val.isNull())
  216. {
  217. QString msg = QCoreApplication::translate(ctkMTMsg::CONTEXT, ctkMTMsg::MISSING_ATTRIBUTE).arg(NAME).arg(name.toString());
  218. _dp_xmlReader.raiseError(msg);
  219. return;
  220. }
  221. QString ocd_description_val = atts.value(DESCRIPTION).toString();
  222. if (ocd_description_val.isNull())
  223. {
  224. // Not a problem, because DESCRIPTION is an optional attribute.
  225. }
  226. QString refID = atts.value(ID).toString();
  227. if (refID.isNull())
  228. {
  229. QString msg = QCoreApplication::translate(ctkMTMsg::CONTEXT, ctkMTMsg::MISSING_ATTRIBUTE).arg(ID).arg(name.toString());
  230. _dp_xmlReader.raiseError(msg);
  231. return;
  232. }
  233. ctkObjectClassDefinitionImplPtr ocd(new ctkObjectClassDefinitionImpl(
  234. ocd_name_val, ocd_description_val,
  235. refID, _dp_localization, _dp_context));
  236. QList<ctkAttributeDefinitionImplPtr> ad_list;
  237. while (!_dp_xmlReader.hasError() && _dp_xmlReader.readNextStartElement())
  238. {
  239. QStringRef name2 = _dp_xmlReader.name();
  240. if (name2.compare(AD, Qt::CaseInsensitive) == 0)
  241. {
  242. attributeDefinitionHandler(ad_list);
  243. }
  244. else if (name2.compare(ICON, Qt::CaseInsensitive) == 0)
  245. {
  246. ctkMTIcon icon = iconHandler();
  247. if (!_dp_xmlReader.hasError())
  248. {
  249. // Because XML schema allows at most one icon for
  250. // one OCD, if more than one icons are read from
  251. // MetaData, then only the final icon will be kept.
  252. ocd->setIcon(icon);
  253. }
  254. }
  255. else
  256. {
  257. CTK_WARN(logger) << QCoreApplication::translate(ctkMTMsg::CONTEXT, ctkMTMsg::UNEXPECTED_ELEMENT).arg(name2.toString());
  258. _dp_xmlReader.skipCurrentElement();
  259. }
  260. }
  261. if (_dp_xmlReader.hasError()) return;
  262. if (ad_list.isEmpty())
  263. {
  264. // Schema defines at least one AD is required.
  265. QString msg = QCoreApplication::translate(ctkMTMsg::CONTEXT, ctkMTMsg::MISSING_ELEMENT).arg(AD).arg(refID);
  266. _dp_xmlReader.raiseError(msg);
  267. return;
  268. }
  269. // OCD gets all parsed ADs.
  270. foreach (ctkAttributeDefinitionImplPtr ad, ad_list)
  271. {
  272. ocd->addAttributeDefinition(ad, ad->isRequired());
  273. }
  274. _dp_OCDs.insert(refID, ocd);
  275. }
  276. void ctkMTDataParser::objectHandler(DesignateInfo& designateInfo)
  277. {
  278. Q_ASSERT(_dp_xmlReader.isStartElement() && _dp_xmlReader.name().compare(OBJECT, Qt::CaseInsensitive) == 0);
  279. designateInfo._ocdref = _dp_xmlReader.attributes().value(OCDREF).toString();
  280. if (designateInfo._ocdref.isNull())
  281. {
  282. QString msg = QCoreApplication::translate(ctkMTMsg::CONTEXT, ctkMTMsg::MISSING_ATTRIBUTE).arg(OCDREF).arg(_dp_xmlReader.name().toString());
  283. _dp_xmlReader.raiseError(msg);
  284. return;
  285. }
  286. while (!_dp_xmlReader.hasError() && _dp_xmlReader.readNextStartElement())
  287. {
  288. QStringRef name = _dp_xmlReader.name();
  289. if (name.compare(ATTRIBUTE, Qt::CaseInsensitive) == 0)
  290. {
  291. attributeHandler();
  292. }
  293. else
  294. {
  295. CTK_WARN(logger) << QCoreApplication::translate(ctkMTMsg::CONTEXT, ctkMTMsg::UNEXPECTED_ELEMENT).arg(name.toString());
  296. _dp_xmlReader.skipCurrentElement();
  297. }
  298. }
  299. }
  300. void ctkMTDataParser::attributeHandler()
  301. {
  302. Q_ASSERT(_dp_xmlReader.isStartElement() && _dp_xmlReader.name().compare(ATTRIBUTE, Qt::CaseInsensitive) == 0);
  303. while (_dp_xmlReader.readNextStartElement()) _dp_xmlReader.skipCurrentElement();
  304. }
  305. void ctkMTDataParser::attributeDefinitionHandler(QList<ctkAttributeDefinitionImplPtr>& ad_list)
  306. {
  307. Q_ASSERT(_dp_xmlReader.isStartElement() && _dp_xmlReader.name().compare(AD, Qt::CaseInsensitive) == 0);
  308. QString name = _dp_xmlReader.name().toString();
  309. QXmlStreamAttributes atts = _dp_xmlReader.attributes();
  310. QString ad_name_val = atts.value(NAME).toString();
  311. if (ad_name_val.isNull())
  312. {
  313. // Not a problem, because NAME is an optional attribute.
  314. }
  315. QString ad_description_val = atts.value(DESCRIPTION).toString();
  316. if (ad_description_val.isNull())
  317. {
  318. // Not a problem, because DESCRIPTION is an optional attribute.
  319. }
  320. QString ad_id_val = atts.value(ID).toString();
  321. if (ad_id_val.isNull())
  322. {
  323. QString msg = QCoreApplication::translate(ctkMTMsg::CONTEXT, ctkMTMsg::MISSING_ATTRIBUTE).arg(ID).arg(name);
  324. _dp_xmlReader.raiseError(msg);
  325. return;
  326. }
  327. int dataType;
  328. QStringRef ad_type_val = atts.value("", TYPE);
  329. if (ad_type_val.compare(STRING, Qt::CaseInsensitive) == 0)
  330. {
  331. dataType = QVariant::String;
  332. }
  333. else if (ad_type_val.compare(LONG, Qt::CaseInsensitive) == 0)
  334. {
  335. dataType = QVariant::LongLong;
  336. }
  337. else if (ad_type_val.compare(DOUBLE, Qt::CaseInsensitive) == 0)
  338. {
  339. dataType = QVariant::Double;
  340. }
  341. else if (ad_type_val.compare(INTEGER, Qt::CaseInsensitive) == 0)
  342. {
  343. dataType = QVariant::Int;
  344. }
  345. else if (ad_type_val.compare(CHAR, Qt::CaseInsensitive) == 0)
  346. {
  347. dataType = QVariant::Char;
  348. }
  349. else if (ad_type_val.compare(BOOLEAN, Qt::CaseInsensitive) == 0)
  350. {
  351. dataType = QVariant::Bool;
  352. }
  353. else if (ad_type_val.compare(PASSWORD, Qt::CaseInsensitive) == 0)
  354. {
  355. dataType = ctkAttributeDefinition::PASSWORD;
  356. }
  357. else
  358. {
  359. QString msg = QCoreApplication::translate(ctkMTMsg::CONTEXT, ctkMTMsg::MISSING_ATTRIBUTE).arg(TYPE).arg(name);
  360. _dp_xmlReader.raiseError(msg);
  361. return;
  362. }
  363. QString ad_cardinality_str = atts.value(CARDINALITY).toString();
  364. int ad_cardinality_val = 0;
  365. if (ad_cardinality_str.isNull())
  366. {
  367. // Not a problem, because CARDINALITY is an optional attribute.
  368. // And the default value is 0.
  369. }
  370. else
  371. {
  372. ad_cardinality_val = ad_cardinality_str.toInt();
  373. }
  374. QString ad_min_val = atts.value(MIN).toString();
  375. if (ad_min_val.isNull())
  376. {
  377. // Not a problem, because MIN is an optional attribute.
  378. }
  379. QString ad_max_val = atts.value(MAX).toString();
  380. if (ad_max_val.isNull())
  381. {
  382. // Not a problem, because MAX is an optional attribute.
  383. }
  384. QString ad_defaults_str = atts.value(DEFAULT).toString();
  385. if (ad_defaults_str.isNull())
  386. {
  387. // Not a problem, because DEFAULT is an optional attribute.
  388. if (ad_cardinality_val == 0)
  389. {
  390. // But when it is not assigned, CARDINALITY cannot be '0'.
  391. QString msg = QCoreApplication::translate(ctkMTMsg::CONTEXT, ctkMTMsg::NULL_DEFAULTS);
  392. _dp_xmlReader.raiseError(msg);
  393. return;
  394. }
  395. }
  396. QString ad_required_val = atts.value(REQUIRED).toString();
  397. if (ad_required_val.isNull())
  398. {
  399. // Not a problem, because REQUIRED is an optional attribute.
  400. // And the default value is 'true'.
  401. ad_required_val = "true";
  402. }
  403. ctkAttributeDefinitionImplPtr ad(new ctkAttributeDefinitionImpl(
  404. ad_id_val, ad_name_val, ad_description_val, dataType,
  405. ad_cardinality_val, convert(ad_min_val, dataType), convert(ad_max_val, dataType),
  406. toBool(ad_required_val), _dp_localization, _dp_context, logger));
  407. if (ad_cardinality_val == 0)
  408. {
  409. // Attribute DEFAULT has one and only one occurance.
  410. ad->setDefaultValue(QStringList(ad_defaults_str), false);
  411. }
  412. else
  413. {
  414. // Attribute DEFAULT is a comma delimited list.
  415. ad->setDefaultValue(ad_defaults_str, false);
  416. }
  417. QStringList optionLabels;
  418. QStringList optionValues;
  419. while (!_dp_xmlReader.hasError() && _dp_xmlReader.readNextStartElement())
  420. {
  421. QStringRef name2 = _dp_xmlReader.name();
  422. if (name2.compare(OPTION, Qt::CaseInsensitive) == 0)
  423. {
  424. OptionInfo optionInfo;
  425. optionHandler(optionInfo);
  426. if (!_dp_xmlReader.hasError())
  427. {
  428. optionLabels.push_back(optionInfo._label_val);
  429. optionValues.push_back(optionInfo._value_val);
  430. }
  431. }
  432. else
  433. {
  434. CTK_WARN(logger) << QCoreApplication::translate(ctkMTMsg::CONTEXT, ctkMTMsg::UNEXPECTED_ELEMENT).arg(name2.toString());
  435. _dp_xmlReader.skipCurrentElement();
  436. }
  437. }
  438. if (_dp_xmlReader.hasError()) return;
  439. ad->setOption(optionLabels, optionValues, true);
  440. ad_list.push_back(ad);
  441. }
  442. ctkMTIcon ctkMTDataParser::iconHandler()
  443. {
  444. Q_ASSERT(_dp_xmlReader.isStartElement() && _dp_xmlReader.name().compare(ICON, Qt::CaseInsensitive) == 0);
  445. QXmlStreamAttributes atts = _dp_xmlReader.attributes();
  446. QString icon_resource_val = atts.value(RESOURCE).toString();
  447. if (icon_resource_val.isNull())
  448. {
  449. QString msg = QCoreApplication::translate(ctkMTMsg::CONTEXT, ctkMTMsg::MISSING_ATTRIBUTE).arg(RESOURCE).arg(_dp_xmlReader.name().toString());
  450. _dp_xmlReader.raiseError(msg);
  451. return ctkMTIcon();
  452. }
  453. QString icon_size_val = atts.value(SIZE).toString();
  454. if (icon_size_val.isNull())
  455. {
  456. // Not a problem, because SIZE is an optional attribute.
  457. icon_size_val = "0";
  458. }
  459. while (_dp_xmlReader.readNextStartElement()) _dp_xmlReader.skipCurrentElement();
  460. return ctkMTIcon(icon_resource_val, icon_size_val.toInt(), _dp_plugin);
  461. }
  462. void ctkMTDataParser::optionHandler(OptionInfo& optionInfo)
  463. {
  464. Q_ASSERT(_dp_xmlReader.isStartElement() && _dp_xmlReader.name().compare(OPTION, Qt::CaseInsensitive) == 0);
  465. QXmlStreamAttributes atts = _dp_xmlReader.attributes();
  466. optionInfo._label_val = atts.value(LABEL).toString();
  467. if (optionInfo._label_val.isNull())
  468. {
  469. QString msg = QCoreApplication::translate(ctkMTMsg::CONTEXT, ctkMTMsg::MISSING_ATTRIBUTE).arg(LABEL).arg(_dp_xmlReader.name().toString());
  470. _dp_xmlReader.raiseError(msg);
  471. return;
  472. }
  473. optionInfo._value_val = atts.value(VALUE).toString();
  474. if (optionInfo._value_val.isNull())
  475. {
  476. QString msg = QCoreApplication::translate(ctkMTMsg::CONTEXT, ctkMTMsg::MISSING_ATTRIBUTE).arg(VALUE).arg(_dp_xmlReader.name().toString());
  477. _dp_xmlReader.raiseError(msg);
  478. return;
  479. }
  480. while (_dp_xmlReader.readNextStartElement()) _dp_xmlReader.skipCurrentElement();
  481. }
  482. void ctkMTDataParser::errorHandler()
  483. {
  484. switch (_dp_xmlReader.error())
  485. {
  486. case QXmlStreamReader::NotWellFormedError:
  487. CTK_WARN(logger) << "XML Document not well formed at line " << _dp_xmlReader.lineNumber() << ", col " << _dp_xmlReader.columnNumber();
  488. break;
  489. case QXmlStreamReader::PrematureEndOfDocumentError:
  490. CTK_WARN(logger) << "Premature end of XML Document at line " << _dp_xmlReader.lineNumber() << ", col " << _dp_xmlReader.columnNumber();
  491. break;
  492. case QXmlStreamReader::UnexpectedElementError:
  493. CTK_WARN(logger) << "Unexpected element at line " << _dp_xmlReader.lineNumber() << ", col " << _dp_xmlReader.columnNumber();
  494. break;
  495. case QXmlStreamReader::CustomError:
  496. CTK_ERROR(logger) << _dp_xmlReader.errorString() << "at line" << _dp_xmlReader.lineNumber() << ", col " << _dp_xmlReader.columnNumber();
  497. break;
  498. default:
  499. break;
  500. }
  501. }
  502. bool ctkMTDataParser::toBool(const QString& str)
  503. {
  504. if (str.isEmpty()) return false;
  505. if (str.trimmed().compare("true", Qt::CaseInsensitive)) return true;
  506. if (str.trimmed().compare("1")) return true;
  507. return false;
  508. }
  509. QVariant ctkMTDataParser::convert(const QString& value, int type)
  510. {
  511. if (value.isNull())
  512. {
  513. return QVariant();
  514. }
  515. if (type == ctkAttributeDefinition::PASSWORD || type == QVariant::String)
  516. {
  517. // PASSWORD should be treated like STRING.
  518. // Both the min and max of STRING are Integers.
  519. return QVariant::fromValue<int>(value.toInt());
  520. }
  521. else if (type == QVariant::LongLong)
  522. {
  523. return QVariant::fromValue<qlonglong>(value.toLongLong());
  524. }
  525. else if (type == QVariant::Int)
  526. {
  527. return QVariant::fromValue<int>(value.toInt());
  528. }
  529. else if (type == QVariant::Char)
  530. {
  531. return QVariant::fromValue<QChar>(value.at(0));
  532. }
  533. else if (type == QVariant::Double)
  534. {
  535. return QVariant::fromValue<double>(value.toDouble());
  536. }
  537. else if (type == QVariant::Bool)
  538. {
  539. return QVariant::fromValue<bool>(toBool(value));
  540. }
  541. else
  542. {
  543. // Unknown data type
  544. return QVariant();
  545. }
  546. }