ctkAttributeDefinitionImpl.cpp 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  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 "ctkAttributeDefinitionImpl_p.h"
  16. #include "ctkMTMsg_p.h"
  17. #include <service/log/ctkLogService.h>
  18. #include <QCoreApplication>
  19. const QChar ctkAttributeDefinitionImpl::SEPARATE = ',';
  20. const QChar ctkAttributeDefinitionImpl::CONTROL = '\\';
  21. ctkAttributeDefinitionImpl::ctkAttributeDefinitionImpl(
  22. const QString& id, const QString& name, const QString& description,
  23. int type, int cardinality, const QVariant& min, const QVariant& max,
  24. bool isRequired, const QString& localization, const QString& context, ctkLogService* logger)
  25. : _name(name), _id(id), _description(description), _cardinality(cardinality),
  26. _dataType(type), _minValue(min), _maxValue(max), _isRequired(isRequired),
  27. _locElem(localization, context), _logger(logger)
  28. {
  29. }
  30. QString ctkAttributeDefinitionImpl::getName() const
  31. {
  32. return _locElem.getLocalized(_name);
  33. }
  34. void ctkAttributeDefinitionImpl::setName(const QString& name)
  35. {
  36. _name = name;
  37. }
  38. QString ctkAttributeDefinitionImpl::getID() const
  39. {
  40. return _id;
  41. }
  42. void ctkAttributeDefinitionImpl::setID(const QString& id)
  43. {
  44. _id = id;
  45. }
  46. QString ctkAttributeDefinitionImpl::getDescription() const
  47. {
  48. return _locElem.getLocalized(_description);
  49. }
  50. void ctkAttributeDefinitionImpl::setDescription(const QString& description)
  51. {
  52. _description = description;
  53. }
  54. int ctkAttributeDefinitionImpl::getCardinality() const
  55. {
  56. return _cardinality;
  57. }
  58. void ctkAttributeDefinitionImpl::setCardinality(int cardinality)
  59. {
  60. _cardinality = cardinality;
  61. }
  62. int ctkAttributeDefinitionImpl::getType() const
  63. {
  64. return _dataType;
  65. }
  66. void ctkAttributeDefinitionImpl::setType(int type)
  67. {
  68. _dataType = type;
  69. }
  70. bool ctkAttributeDefinitionImpl::isRequired() const
  71. {
  72. return _isRequired;
  73. }
  74. void ctkAttributeDefinitionImpl::setRequired(bool isRequired)
  75. {
  76. _isRequired = isRequired;
  77. }
  78. QStringList ctkAttributeDefinitionImpl::getOptionLabels() const
  79. {
  80. if (_labels.isEmpty())
  81. {
  82. return QStringList();
  83. }
  84. QStringList returnedLabels;
  85. foreach(QString labelKey, _labels)
  86. {
  87. returnedLabels << _locElem.getLocalized(labelKey);
  88. }
  89. return returnedLabels;
  90. }
  91. QStringList ctkAttributeDefinitionImpl::getOptionValues() const
  92. {
  93. return _values;
  94. }
  95. void ctkAttributeDefinitionImpl::setOption(
  96. const QStringList& labels, const QStringList& values, bool needValidation)
  97. {
  98. // if (labels.isEmpty() || values.isEmpty())
  99. // {
  100. // CTK_ERROR(_logger) << "ctkAttributeDefinitionImpl::setOption(QStringList, QStringList, bool)"
  101. // << QCoreApplication::translate(ctkMTMsg::CONTEXT, ctkMTMsg::NULL_OPTIONS);
  102. // return;
  103. // }
  104. if (labels.size() != values.size())
  105. {
  106. CTK_ERROR(_logger) << "ctkAttributeDefinitionImpl::setOption(QStringList, QStringList, bool)"
  107. << QCoreApplication::translate(ctkMTMsg::CONTEXT, ctkMTMsg::INCONSISTENT_OPTIONS);
  108. return;
  109. }
  110. _labels = labels;
  111. _values = values;
  112. if (needValidation)
  113. {
  114. for (int index = 0; index < _labels.size(); index++)
  115. {
  116. QString reason = validate(_values.value(index));
  117. if (!reason.isEmpty())
  118. {
  119. CTK_WARN(_logger) << QCoreApplication::translate(ctkMTMsg::CONTEXT, ctkMTMsg::INVALID_OPTIONS).arg(_values.value(index)).arg(reason);
  120. _labels.removeAt(index);
  121. _values.removeAt(index);
  122. index--; // Because this one has been removed.
  123. }
  124. }
  125. }
  126. }
  127. QStringList ctkAttributeDefinitionImpl::getDefaultValue() const
  128. {
  129. return _defaults;
  130. }
  131. void ctkAttributeDefinitionImpl::setDefaultValue(const QString& defaults_str, bool needValidation)
  132. {
  133. setDefaultValue(tokenizeValues(defaults_str), needValidation);
  134. }
  135. void ctkAttributeDefinitionImpl::setDefaultValue(const QStringList& defaults, bool needValidation)
  136. {
  137. Q_UNUSED(needValidation)
  138. _defaults = defaults;
  139. // Do we also need to make sure if defaults are validated?
  140. }
  141. void ctkAttributeDefinitionImpl::setMinValue(const QVariant& minValue)
  142. {
  143. _minValue = minValue;
  144. }
  145. void ctkAttributeDefinitionImpl::setMaxValue(const QVariant& maxValue)
  146. {
  147. _maxValue = maxValue;
  148. }
  149. void ctkAttributeDefinitionImpl::setPluginLocalization(const ctkPluginLocalization& pluginLoc)
  150. {
  151. _locElem.setPluginLocalization(pluginLoc);
  152. }
  153. QString ctkAttributeDefinitionImpl::validate(const QString& value) const
  154. {
  155. if (value.isNull())
  156. {
  157. return QCoreApplication::translate(ctkMTMsg::CONTEXT, ctkMTMsg::NULL_IS_INVALID);
  158. }
  159. if ((_minValue.isNull()) && (_maxValue.isNull()))
  160. {
  161. // Password is treated like String.
  162. if (_dataType != QVariant::String && _dataType != QVariant::UserType)
  163. {
  164. // No validation present
  165. return QString();
  166. }
  167. if (_values.size() < 1)
  168. // No validation present
  169. return QString();
  170. }
  171. // Addtional validation for STRING.
  172. // PASSWORD is treated like STRING.
  173. if ((_dataType == QVariant::String || _dataType == QVariant::UserType) && _values.size() > 0 && !_values.contains(value))
  174. {
  175. return QCoreApplication::translate(ctkMTMsg::CONTEXT, ctkMTMsg::VALUE_OUT_OF_OPTION).arg(value);
  176. }
  177. try
  178. {
  179. if (_cardinality != 0)
  180. {
  181. QStringList value_list = tokenizeValues(value);
  182. if (value_list.size() > _cardinality)
  183. {
  184. return QCoreApplication::translate(ctkMTMsg::CONTEXT, ctkMTMsg::TOO_MANY_VALUES).arg(value).arg(_cardinality);
  185. }
  186. for (int i = 0; i < value_list.size(); i++)
  187. {
  188. QString return_msg = validateRange(value_list.value(i));
  189. if (!return_msg.isEmpty())
  190. {
  191. // Returned String states why the value is invalid.
  192. return return_msg;
  193. }
  194. }
  195. // No problems detected
  196. return "";
  197. }
  198. // Only when cardinality is '0', it comes here.
  199. QString return_msg = validateRange(value);
  200. return return_msg;
  201. }
  202. catch (const std::exception& e)
  203. {
  204. return QCoreApplication::translate(ctkMTMsg::CONTEXT, ctkMTMsg::EXCEPTION_MESSAGE).arg("std::exception").arg(e.what());
  205. }
  206. }
  207. QString ctkAttributeDefinitionImpl::validateRange(const QString& value) const
  208. {
  209. bool rangeError = false;
  210. switch (_dataType)
  211. {
  212. // PASSWORD is treated like STRING.
  213. case QVariant::UserType:
  214. case QVariant::String:
  215. {
  216. if (!_minValue.isNull() && value.length() < _minValue.toInt())
  217. {
  218. rangeError = true;
  219. }
  220. else if (!_maxValue.isNull() && value.length() > _maxValue.toInt())
  221. {
  222. rangeError = true;
  223. }
  224. break;
  225. }
  226. case QVariant::LongLong:
  227. {
  228. qlonglong longVal = value.toLongLong();
  229. if (!_minValue.isNull() && longVal < _minValue.toLongLong())
  230. {
  231. rangeError = true;
  232. }
  233. else if (!_maxValue.isNull() && longVal > _maxValue.toLongLong())
  234. {
  235. rangeError = true;
  236. }
  237. break;
  238. }
  239. case QVariant::Int:
  240. {
  241. int intVal = value.toInt();
  242. if (!_minValue.isNull() && intVal < _minValue.toInt())
  243. {
  244. rangeError = true;
  245. }
  246. else if (!_maxValue.isNull() && intVal > _maxValue.toInt())
  247. {
  248. rangeError = true;
  249. }
  250. break;
  251. }
  252. case QVariant::Char:
  253. {
  254. QChar charVal = value.at(0);
  255. if (!_minValue.isNull() && charVal < _minValue.toChar())
  256. {
  257. rangeError = true;
  258. }
  259. else if (!_maxValue.isNull() && charVal > _maxValue.toChar())
  260. {
  261. rangeError = true;
  262. }
  263. break;
  264. }
  265. case QVariant::Double:
  266. {
  267. double doubleVal = value.toDouble();
  268. if (!_minValue.isNull() && doubleVal < _minValue.toDouble())
  269. {
  270. rangeError = true;
  271. }
  272. else if (!_maxValue.isNull() && doubleVal > _maxValue.toDouble())
  273. {
  274. rangeError = true;
  275. }
  276. break;
  277. }
  278. case QVariant::Bool:
  279. // shouldn't ever get boolean - this is a range validation
  280. default :
  281. return QString();
  282. }
  283. if (rangeError)
  284. {
  285. return QCoreApplication::translate(ctkMTMsg::CONTEXT, ctkMTMsg::VALUE_OUT_OF_RANGE).arg(value);
  286. }
  287. // No problems detected
  288. return "";
  289. }
  290. QStringList ctkAttributeDefinitionImpl::tokenizeValues(const QString& values) const
  291. {
  292. QStringList result;
  293. if (!values.isEmpty())
  294. {
  295. QString buffer;
  296. for (int i = 0; i < values.size(); i++)
  297. {
  298. if (values.at(i) == CONTROL)
  299. {
  300. if (i + 1 < values.size())
  301. {
  302. buffer.append(values.at(++i));
  303. continue;
  304. }
  305. // CONTROL char should not occur in last char.
  306. CTK_ERROR(_logger) << QCoreApplication::translate(ctkMTMsg::CONTEXT, ctkMTMsg::TOKENIZER_GOT_INVALID_DATA);
  307. // It's an invalid char, but since it's the last one,
  308. // just ignore it.
  309. continue;
  310. }
  311. if (values.at(i) == SEPARATE)
  312. {
  313. result.push_back(buffer.trimmed());
  314. buffer.clear();
  315. continue;
  316. }
  317. buffer.append(values.at(i));
  318. }
  319. // Don't forget the final one.
  320. result.push_back(buffer.trimmed());
  321. }
  322. return result;
  323. }