knowL: Knowledge Libraries
Loading...
Searching...
No Matches
QuantityValue.h
1#pragma once
2
3#include <QCryptographicHash>
4#include <QJsonObject>
5#include <QCborMap>
6
7#include "BigNumber.h"
8#include "NamedTypes.h"
9#include "Unit.h"
10#include "Value.h"
11
12namespace knowCore
13{
19 template<typename _T_>
21 {
22 template<typename _TOther_, typename _Enabled_ = void>
23 struct Constructor;
24 public:
25 QuantityValue() {}
26 QuantityValue(const _T_& _value, const Unit& _unit);
28 template<typename _TOther_, typename _TUri_, std::enable_if_t<not std::is_base_of_v<Value, _TOther_>, bool> = true>
29 static std::enable_if_t<knowCore::Uris::IsUriDefinitionV<_TUri_>, ReturnValue<QuantityValue>> create(const _TOther_& _value, const _TUri_& _unit_uri) { return create(_value, knowCore::Uri(_unit_uri)); }
30 template<typename _TOther_, std::enable_if_t<not std::is_base_of_v<Value, _TOther_>, bool> = true>
31 static ReturnValue<QuantityValue> create(const _TOther_& _value, const knowCore::Uri& _unit_uri);
32 static ReturnValue<QuantityValue> create(const Value& _value, const knowCore::Uri& _unit_uri);
33 template<typename _TOther_, std::enable_if_t<not std::is_base_of_v<Value, _TOther_>, bool> = true>
34 static ReturnValue<QuantityValue> create(const _TOther_& _value, const QString& _unit_uri) = delete;
35 static ReturnValue<QuantityValue> create(const Value& _value, const QString& _unit_uri) = delete;
36 template<typename _TOther_, std::enable_if_t<not std::is_base_of_v<Value, _TOther_>, bool> = true>
37 static ReturnValue<QuantityValue> create(const _TOther_& _value, const Symbol& _unit_symbol);
38 static ReturnValue<QuantityValue> create(const Value& _value, const Symbol& _unit_symbol);
39
43 Unit unit() const { return m_unit; }
47 _T_ value() const { return m_value; }
48
68 QuantityValue operator/(const _T_& _rhs) const;
72 QuantityValue operator*(const _T_& _rhs) const;
73
77 bool operator==(const QuantityValue& _rhs) const;
81 ReturnValue<bool> operator<(const QuantityValue& _rhs) const;
82
90 ReturnValue<QJsonValue> toJsonValue(const SerialisationContexts& _contexts = defaultSerialisationContext()) const;
94 static ReturnValue<QuantityValue> fromJsonValue(const QJsonValue& _value, const DeserialisationContexts& _context = defaultDeserialisationContext());
98 ReturnValue<QCborValue> toCborValue(const SerialisationContexts& _contexts = defaultSerialisationContext()) const;
102 static ReturnValue<QuantityValue> fromCborValue(const QCborValue& _value, const DeserialisationContexts& _context = defaultDeserialisationContext());
106 ReturnValue<QString> toRdfLiteral(const SerialisationContexts& _contexts = defaultSerialisationContext()) const;
110 static ReturnValue<QuantityValue> fromRdfLiteral(const QString& _value, const DeserialisationContexts& _context = defaultDeserialisationContext());
115 private:
116 ReturnValue<_T_> cast_rhs(const QuantityValue& _rhs) const;
117 _T_ m_value;
118 Unit m_unit;
119 };
123 template<typename _T_>
124 QuantityValue<_T_> operator*(const _T_& _lhs, const QuantityValue<_T_>& _rhs);
125
126 //BEGIN Specialized constructors
127 template<>
128 template<typename _TOther_>
129 struct QuantityValue<BigNumber>::Constructor<_TOther_, std::enable_if_t<not std::is_same_v<_TOther_, QString>>>
130 {
131 static knowCore::ReturnValue<BigNumber> construct(const _TOther_& _v) { return kCrvSuccess(BigNumber(_v)); }
132 };
133 template<>
134 template<>
135 struct QuantityValue<BigNumber>::Constructor<QString>
136 {
137 static knowCore::ReturnValue<BigNumber> construct(const QString& _v) { return BigNumber::fromString(_v); }
138 };
139 //END Specialized constructors
140
141 //BEGIN implementation
142 template<typename _T_>
143 inline QuantityValue<_T_>::QuantityValue(const _T_& _value, const Unit& _unit) : m_value(_value), m_unit(_unit)
144 {
145 }
146
147 template<typename _T_>
148 template<typename _TOther_, std::enable_if_t<not std::is_base_of_v<Value, _TOther_>, bool>>
149 inline ReturnValue<QuantityValue<_T_>> QuantityValue<_T_>::create(const _TOther_& _value, const knowCore::Uri& _unit_uri)
150 {
151 KNOWCORE_RETURN_VALUE_TRY(unit, Unit::byUri(_unit_uri));
152 return kCrvSuccess(QuantityValue(_value, unit));
153 }
154
155 template<typename _T_>
156 inline ReturnValue<QuantityValue<_T_>> QuantityValue<_T_>::create(const knowCore::Value& _value, const knowCore::Uri& _unit_uri)
157 {
158 KNOWCORE_RETURN_VALUE_TRY(value, _value.value<_T_>());
159 return create(value, _unit_uri);
160 }
161
162 template<typename _T_>
163 template<typename _TOther_, std::enable_if_t<not std::is_base_of_v<Value, _TOther_>, bool>>
164 inline ReturnValue<QuantityValue<_T_>> QuantityValue<_T_>::create(const _TOther_& _value, const Symbol& _unit_symbol)
165 {
166 KNOWCORE_RETURN_VALUE_TRY(unit, Unit::bySymbol(_unit_symbol));
167 KNOWCORE_RETURN_VALUE_TRY(value, Constructor<_TOther_>::construct(_value));
168 return kCrvSuccess(QuantityValue(value, unit));
169 }
170
171 template<typename _T_>
172 inline ReturnValue<QuantityValue<_T_>> QuantityValue<_T_>::create(const Value& _value, const Symbol& _unit_symbol)
173 {
174 KNOWCORE_RETURN_VALUE_TRY(value, _value.value<_T_>());
175 return create(value, _unit_symbol);
176 }
177
178 template<typename _T_>
179 inline ReturnValue<_T_> QuantityValue<_T_>::cast_rhs(const QuantityValue& _rhs) const
180 {
181 if(_rhs.unit().base() == unit().base())
182 {
183 return kCrvSuccess(_rhs.value() * _rhs.unit().scale() / unit().scale());
184 } else {
185 return kCrvError("Cannot operate on incompatible units: {} is not compatible with {}", unit(), _rhs.unit());
186 }
187 }
188
189 template<typename _T_>
191 {
192 KNOWCORE_RETURN_VALUE_TRY(rhsv, cast_rhs(_rhs));
193 return kCrvSuccess<QuantityValue<_T_>>({value() + rhsv, unit()});
194 }
195 template<typename _T_>
197 {
198 KNOWCORE_RETURN_VALUE_TRY(rhsv, cast_rhs(_rhs));
199 return kCrvSuccess<QuantityValue<_T_>>({value() - rhsv, unit()});
200 }
201 template<typename _T_>
203 {
204 if(unit().base() == _rhs.unit().base())
205 {
206 KNOWCORE_RETURN_VALUE_TRY(rhsv, cast_rhs(_rhs));
207 return kCrvSuccess<QuantityValue<_T_>>({value() / rhsv, Unit::empty()});
208 } else {
209 KNOWCORE_RETURN_VALUE_TRY(runit, unit() / _rhs.unit());
210 return kCrvSuccess<QuantityValue<_T_>>({value() / _rhs.value(), runit});
211 }
212 }
213 template<typename _T_>
215 {
216 if(unit().base() == _rhs.unit().base())
217 {
218 KNOWCORE_RETURN_VALUE_TRY(rhsv, cast_rhs(_rhs));
219 KNOWCORE_RETURN_VALUE_TRY(runit, unit() * unit());
220 return kCrvSuccess<QuantityValue<_T_>>({value() * rhsv, runit});
221 } else {
222 KNOWCORE_RETURN_VALUE_TRY(runit, unit() * _rhs.unit());
223 return kCrvSuccess<QuantityValue<_T_>>({value() * _rhs.value(), runit});
224 }
225 }
226
227 template<typename _T_>
229 {
230 return QuantityValue<_T_>{value() / _rhs, unit()};
231 }
232
233 template<typename _T_>
235 {
236 return QuantityValue<_T_>{value() * _rhs, unit()};
237 }
238
239 template<typename _T_>
240 QuantityValue<_T_> operator*(const _T_& _lhs, const QuantityValue<_T_>& _rhs)
241 {
242 return _rhs * _lhs;
243 }
244
245
246 template<typename _T_>
248 {
249 return value() == _rhs.value() and unit() == _rhs.unit();
250 }
251
252 template<typename _T_>
254 {
255 KNOWCORE_RETURN_VALUE_TRY(rhsv, cast_rhs(_rhs));
256 return kCrvSuccess(value() < rhsv);
257 }
258
259 template<typename _T_>
261 {
262 QCryptographicHash hash(QCryptographicHash::Md5);
263 KNOWCORE_RETURN_VALUE_TRY(value_md5, MetaTypeInformation<_T_>::md5(m_value));
264 hash.addData(value_md5);
265 hash.addData(unit().symbol().toUtf8());
266 return kCrvSuccess(hash.result());
267 }
268
269#define __KNOWCORE_VALUE_KEY QString("value")
270#define __KNOWCORE_UNIT_KEY QString("unit")
271
272 template<typename _T_>
274 {
275 QJsonObject object;
276 KNOWCORE_RETURN_VALUE_TRY_ASSIGN(object[__KNOWCORE_VALUE_KEY], MetaTypeInformation<_T_>::toJsonValue(value(), _contexts));
277 object[__KNOWCORE_UNIT_KEY] = unit().symbol();
278 return kCrvSuccess(object);
279 }
280
281 template<typename _T_>
283 {
284 if(_value.isObject())
285 {
286 QJsonObject object = _value.toObject();
287 KNOWCORE_RETURN_VALUE_TRY(value, MetaTypeInformation<_T_>::fromJsonValue(object.value(__KNOWCORE_VALUE_KEY), _context));
288 KNOWCORE_RETURN_VALUE_TRY(unit, Unit::bySymbol(object.value(__KNOWCORE_UNIT_KEY).toString()));
289 return kCrvSuccess<QuantityValue<_T_>>({value, unit});
290 } else {
291 return kCrvError("Expected object got {}", _value);
292 }
293 }
294
295 template<typename _T_>
297 {
298 QCborMap object;
299 KNOWCORE_RETURN_VALUE_TRY_ASSIGN(object[__KNOWCORE_VALUE_KEY], MetaTypeInformation<_T_>::toCborValue(value(), _contexts));
300 object[__KNOWCORE_UNIT_KEY] = unit().symbol();
301 return kCrvSuccess(object);
302 }
303
304 template<typename _T_>
306 {
307 if(_value.isMap())
308 {
309 QCborMap object = _value.toMap();
310 KNOWCORE_RETURN_VALUE_TRY(value, MetaTypeInformation<_T_>::fromCborValue(object.value(__KNOWCORE_VALUE_KEY), _context));
311 KNOWCORE_RETURN_VALUE_TRY(unit, Unit::bySymbol(object.value(__KNOWCORE_UNIT_KEY).toString()));
312 return kCrvSuccess<QuantityValue<_T_>>({value, unit});
313 } else {
314 return kCrvError("Expected object got {}", _value);
315 }
316 }
317
318 template<typename _T_>
320 {
321 KNOWCORE_RETURN_VALUE_TRY(str, MetaTypeInformation<_T_>::toRdfLiteral(value(), _contexts));
322 return kCrvSuccess(str + " " + m_unit.symbol());
323 }
324
325 template<typename _T_>
327 {
328 QStringList splited = _value.split(" ", KNOWCORE_QT_SKIP_EMPTY_PART);
329 if(splited.size() == 0)
330 {
331 return kCrvError("Empty literal");
332 }
333 Unit u = Unit::empty();
334 if(splited.size() == 2)
335 {
336 KNOWCORE_RETURN_VALUE_TRY_ASSIGN(u, Unit::bySymbol(splited[1]));
337 }
338 KNOWCORE_RETURN_VALUE_TRY(value, MetaTypeInformation<_T_>::fromRdfLiteral(splited[0], _context));
339 return kCrvSuccess<QuantityValue<_T_>>({value, u});
340 }
341
342 template<typename _T_>
344 {
345 return toRdfLiteral();
346 }
347
348#undef __KNOWCORE_UNIT_KEY
349#undef __KNOWCORE_VALUE_KEY
350
351 //END implementation
352}
353
354#include "MetaType.h"
355KNOWCORE_DECLARE_FULL_METATYPE(knowCore, QuantityNumber)
356
357template<typename _T_>
358struct fmt::formatter<knowCore::QuantityValue<_T_>> : public clog_fmt::base_formatter {
359 template <typename FormatContext>
360 auto format(knowCore::QuantityValue<_T_> const& p, FormatContext& ctx) -> decltype(ctx.out())
361 {
362 return format_to(ctx.out(), "({} {})", p.value(), p.unit());
363 }
364};
Class that can contains large numeric value.
Definition BigNumber.h:46
Definition MetaType.h:114
Definition MetaType.h:58
Definition NamedType.h:40
Definition QuantityValue.h:21
Unit unit() const
Definition QuantityValue.h:43
ReturnValue< QuantityValue > operator-(const QuantityValue &_rhs) const
Definition QuantityValue.h:196
ReturnValue< QString > toRdfLiteral(const SerialisationContexts &_contexts=defaultSerialisationContext()) const
Definition QuantityValue.h:319
bool operator==(const QuantityValue &_rhs) const
Definition QuantityValue.h:247
ReturnValue< QuantityValue > operator+(const QuantityValue &_rhs) const
Definition QuantityValue.h:190
ReturnValue< QString > printable() const
Definition QuantityValue.h:343
_T_ value() const
Definition QuantityValue.h:47
ReturnValue< bool > operator<(const QuantityValue &_rhs) const
Definition QuantityValue.h:253
static ReturnValue< QuantityValue > fromJsonValue(const QJsonValue &_value, const DeserialisationContexts &_context=defaultDeserialisationContext())
Definition QuantityValue.h:282
static ReturnValue< QuantityValue > fromCborValue(const QCborValue &_value, const DeserialisationContexts &_context=defaultDeserialisationContext())
Definition QuantityValue.h:305
ReturnValue< QuantityValue > operator/(const QuantityValue &_rhs) const
Definition QuantityValue.h:202
ReturnValue< QuantityValue > operator*(const QuantityValue &_rhs) const
Definition QuantityValue.h:214
static ReturnValue< QuantityValue > fromRdfLiteral(const QString &_value, const DeserialisationContexts &_context=defaultDeserialisationContext())
Definition QuantityValue.h:326
ReturnValue< QByteArray > md5() const
Definition QuantityValue.h:260
ReturnValue< QJsonValue > toJsonValue(const SerialisationContexts &_contexts=defaultSerialisationContext()) const
Definition QuantityValue.h:273
ReturnValue< QCborValue > toCborValue(const SerialisationContexts &_contexts=defaultSerialisationContext()) const
Definition QuantityValue.h:296
Definition ReturnValue.h:29
Definition MetaType.h:145
Definition Unit.h:16
static ReturnValue< Unit > bySymbol(const QString &_symbol)
Definition Unit.cpp:404
static ReturnValue< Unit > byUri(const knowCore::Uri &_symbol)
Definition Unit.cpp:424
Unit base() const
Definition Unit.cpp:259
QString symbol() const
Definition Unit.cpp:244
Definition Uri.h:14
Definition Value.h:13
ReturnValue< _T_ > value(TypeCheckingMode _conversion=TypeCheckingMode::Safe) const
Definition Value.h:229