Mantid
Loading...
Searching...
No Matches
PropertyWithValue.hxx
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
8
10#include "MantidKernel/Logger.h"
16
17#ifndef Q_MOC_RUN
18#include <boost/algorithm/string/trim.hpp>
19#include <memory>
20#endif
21
24#include "MantidNexus/NexusFile.h"
25#include <json/value.h>
26#include <type_traits>
27#include <vector>
28
29namespace Mantid {
30namespace Kernel {
31
32//------------------------------------------------------------------------------------------------
33// Now the PropertyWithValue class itself
34//------------------------------------------------------------------------------------------------
35
43template <typename TYPE>
45 unsigned int direction)
46 : Property(std::move(name), typeid(TYPE), direction), m_value(defaultValue),
47 m_initialValue(std::move(defaultValue)), m_validator(std::move(validator)) {}
55template <typename TYPE>
56PropertyWithValue<TYPE>::PropertyWithValue(std::string name, TYPE defaultValue, unsigned int direction)
57 : Property(std::move(name), typeid(TYPE), direction), m_value(defaultValue),
58 m_initialValue(std::move(defaultValue)), m_validator(std::make_shared<NullValidator>()) {}
60/*
61 Constructor to handle vector value assignments to m_initialValue
62 so they can be remembered when the algorithm dialog is reloaded.
63*/
74template <typename TYPE>
75PropertyWithValue<TYPE>::PropertyWithValue(const std::string &name, const TYPE &defaultValue,
76 const std::string &defaultValueStr, IValidator_sptr validator,
77 unsigned int direction)
78 : Property(name, typeid(TYPE), direction), m_value(extractToValueVector<TYPE>(defaultValueStr)),
79 m_initialValue(m_value), m_validator(std::move(validator)) {
80 UNUSED_ARG(defaultValue);
81}
82
87template <typename TYPE>
89 : Property(right), m_value(right.m_value), m_initialValue(right.m_initialValue), // the default is the initial
90 // value of the original object
91 m_validator(right.m_validator->clone()) {}
92
95 return new PropertyWithValue<TYPE>(*this);
96}
97
98template <typename TYPE> void PropertyWithValue<TYPE>::saveProperty(Nexus::File * /*file*/) {
99 // AppleClang 7.3 and later gives a -Winfinite-recursion warning if I call the
100 // base class method. The function is small enough that reimplementing it
101 // isn't a big deal.
102 throw std::invalid_argument("PropertyWithValue::saveProperty - Cannot save '" + this->name() + "', property type " +
103 typeid(TYPE).name() + " not implemented.");
104}
105
109template <typename TYPE> std::string PropertyWithValue<TYPE>::value() const { return toString(m_value); }
110
114template <typename TYPE>
115std::string PropertyWithValue<TYPE>::valueAsPrettyStr(const size_t maxLength, const bool collapseLists) const {
116 std::string retVal;
117 try {
118 retVal = toPrettyString(m_value, maxLength, collapseLists);
119 } catch (boost::bad_lexical_cast &) {
120 // toPrettyStringFailed, default to using toString instead
121 retVal = Strings::shorten(value(), maxLength);
122 }
123 return retVal;
124}
125
130template <typename TYPE> Json::Value PropertyWithValue<TYPE>::valueAsJson() const { return encodeAsJson((*this)()); }
131
137template <typename TYPE> bool PropertyWithValue<TYPE>::operator==(const PropertyWithValue<TYPE> &rhs) const {
138 if (this->name() != rhs.name())
139 return false;
140 return (m_value == rhs.m_value);
141}
142
148template <typename TYPE> bool PropertyWithValue<TYPE>::operator!=(const PropertyWithValue<TYPE> &rhs) const {
149 return !(*this == rhs);
150}
151
154template <typename TYPE> int PropertyWithValue<TYPE>::size() const { return findSize(m_value); }
155
159template <typename TYPE> std::string PropertyWithValue<TYPE>::getDefault() const { return toString(m_initialValue); }
160
168template <typename TYPE> std::string PropertyWithValue<TYPE>::setValue(const std::string &value) {
169 try {
170 TYPE result = m_value;
171 std::string valueCopy = value;
172 if (autoTrim()) {
173 boost::trim(valueCopy);
174 }
175 toValue(valueCopy, result);
176 // Uses the assignment operator defined below which runs isValid() and
177 // throws based on the result
178 *this = result;
179 return "";
180 } catch (boost::bad_lexical_cast &) {
181 std::string error = "Could not set property " + name() + ". Can not convert \"" + value + "\" to " + type();
182 g_logger.debug() << error;
183 return error;
184 } catch (std::invalid_argument &except) {
185 g_logger.debug() << "Could not set property " << name() << ": " << except.what();
186 return except.what();
187 }
188}
189
196template <typename TYPE> std::string PropertyWithValue<TYPE>::setValueFromJson(const Json::Value &value) {
197 if (value.type() != Json::stringValue) {
198 try {
199 *this = decode<TYPE>(value);
200 } catch (std::invalid_argument &exc) {
201 return exc.what();
202 }
203 return "";
204 } else {
205 return setValue(value.asString());
206 }
207}
208
215template <typename TYPE> std::string PropertyWithValue<TYPE>::setDataItem(const std::shared_ptr<DataItem> &data) {
216 // Pass of the helper function that is able to distinguish whether
217 // the TYPE of the PropertyWithValue can be converted to a
218 // shared_ptr<DataItem>
219 return setTypedValue(data, std::is_convertible<TYPE, std::shared_ptr<DataItem>>());
220}
221
224// cppcheck-suppress operatorEqVarError
226 if (&right == this)
227 return *this;
229 m_validator = right.m_validator->clone();
230 return *this;
231}
232
233//--------------------------------------------------------------------------------------
239 PropertyWithValue const *rhs = dynamic_cast<PropertyWithValue const *>(right);
240
241 if (rhs) {
242 // This function basically does:
243 // m_value += rhs->m_value; for values
244 // or concatenates vectors for vectors
245 addingOperator(m_value, rhs->m_value);
246 } else
247 g_logger.warning() << "PropertyWithValue " << this->name()
248 << " could not be added to another property of the "
249 "same name but incompatible type.\n";
250
251 return *this;
252}
253
254//--------------------------------------------------------------------------------------
262 TYPE oldValue = m_value;
263 if constexpr (std::is_same<TYPE, std::string>::value) {
264 std::string valueCopy = toString(value);
265 if (autoTrim()) {
266 boost::trim(valueCopy);
267 }
268 toValue(valueCopy, m_value);
269 } else {
270 m_value = value;
271 }
272 std::string problem = this->isValid();
273 if (problem.empty()) {
274 return *this;
275 } else if (problem == "_alias") {
276 m_value = getValueForAlias(value);
277 return *this;
278 } else {
279 m_value = oldValue;
280 throw std::invalid_argument("When setting value of property \"" + this->name() + "\": " + problem);
281 }
282}
283
288template <typename TYPE> const TYPE &PropertyWithValue<TYPE>::operator()() const { return m_value; }
289
294template <typename TYPE> PropertyWithValue<TYPE>::operator const TYPE &() const { return m_value; }
295
303template <typename TYPE> std::string PropertyWithValue<TYPE>::isValid() const { return m_validator->isValid(m_value); }
304
311template <typename TYPE> bool PropertyWithValue<TYPE>::isDefault() const { return m_initialValue == m_value; }
312
318template <typename TYPE> std::vector<std::string> PropertyWithValue<TYPE>::allowedValues() const {
320}
321
328 return m_validator->isMultipleSelectionAllowed();
329}
330
335template <typename TYPE> void PropertyWithValue<TYPE>::replaceValidator(IValidator_sptr newValidator) {
336 m_validator = newValidator;
337}
338
346template <typename TYPE> std::string PropertyWithValue<TYPE>::setValueFromProperty(const Property &right) {
347
348 if (auto prop = dynamic_cast<const PropertyWithValue<TYPE> *>(&right)) {
349 m_value = prop->m_value;
350 return "";
351 } else {
352 return setValue(right.value());
353 }
354}
355
363template <typename TYPE>
364template <typename U>
365std::string PropertyWithValue<TYPE>::setTypedValue(const U &value, const std::true_type &) {
366 TYPE data = std::dynamic_pointer_cast<typename TYPE::element_type>(value);
367 std::string msg;
368 if (data) {
369 try {
370 (*this) = data;
371 } catch (std::invalid_argument &exc) {
372 msg = exc.what();
373 }
374 } else {
375 msg = "Invalid DataItem. The object type (" + std::string(typeid(value).name()) +
376 ") does not match the declared type of the property (" + std::string(this->type()) + ").";
377 }
378 return msg;
379}
380
388template <typename TYPE>
389template <typename U>
390std::string PropertyWithValue<TYPE>::setTypedValue(const U &value, const std::false_type &) {
392 return "Attempt to assign object of type DataItem to property (" + name() + ") of incorrect type";
393}
394
400template <typename TYPE> const TYPE PropertyWithValue<TYPE>::getValueForAlias(const TYPE &alias) const {
401 std::string strAlias = toString(alias);
402 std::string strValue = m_validator->getValueForAlias(strAlias);
403 TYPE typeValue;
404 toValue(strValue, typeValue);
405 return typeValue;
406}
407
412template <typename TYPE> IValidator_sptr PropertyWithValue<TYPE>::getValidator() const { return m_validator; }
413
414} // namespace Kernel
415} // namespace Mantid
const std::string & m_value
Definition Algorithm.cpp:71
Kernel::IValidator_sptr m_validator
std::string name
Definition Run.cpp:60
const std::vector< double > & rhs
double value
The value of the point.
Definition FitMW.cpp:51
double error
double right
#define UNUSED_ARG(x)
Function arguments are sometimes unused in certain implmentations but are required for documentation ...
Definition System.h:48
NullValidator is a validator that doesn't.
The concrete, templated class for properties.
virtual void replaceValidator(IValidator_sptr newValidator)
Replace the current validator with the given one.
bool isDefault() const override
Indicates if the property's value is the same as it was when it was set N.B.
int size() const override
Get the size of the property.
PropertyWithValue & operator=(const PropertyWithValue &right)
Copy assignment operator assigns only the value and the validator not the name, default (initial) val...
std::string setTypedValue(const U &value, const std::true_type &)
Helper function for setValue(DataItem_sptr).
std::string setValue(const std::string &value) override
Set the value of the property from a string representation.
PropertyWithValue & operator+=(Property const *right) override
Add the value of another property.
std::string valueAsPrettyStr(const size_t maxLength=0, const bool collapseLists=true) const override
Get the value of the property as a string.
Json::Value valueAsJson() const override
Attempt to construct a Json::Value object from the plain value.
bool operator==(const PropertyWithValue< TYPE > &rhs) const
Deep comparison.
bool isMultipleSelectionAllowed() override
Returns the set of valid values for this property, if such a set exists.
void saveProperty(Nexus::File *file) override
PropertyWithValue< TYPE > * clone() const override
'Virtual copy constructor'
const TYPE getValueForAlias(const TYPE &alias) const
Return value for a given alias.
virtual const TYPE & operator()() const
Allows you to get the value of the property via an expression like myProperty()
std::string setValueFromJson(const Json::Value &value) override
Set the value of the property from a Json representation.
IValidator_sptr getValidator() const
Returns the validator as a constant variable so it cannot be changed.
std::vector< std::string > allowedValues() const override
Returns the set of valid values for this property, if such a set exists.
TYPE m_value
The value of the property.
std::string value() const override
Get the value of the property as a string.
std::string isValid() const override
Check the value chosen for the property is OK, unless overidden it just calls the validator's isValid...
bool operator!=(const PropertyWithValue< TYPE > &rhs) const
Deep comparison (not equal).
std::string setValueFromProperty(const Property &right) override
Set the value of the property via a reference to another property.
std::string setDataItem(const std::shared_ptr< DataItem > &data) override
Set a property value via a DataItem.
std::string getDefault() const override
Get the value the property was initialised with -its default value.
Base class for properties.
Definition Property.h:94
const std::string & name() const
Get the property's name.
Definition Property.cpp:61
MANTID_KERNEL_DLL std::string shorten(const std::string &input, const size_t max_length)
Converts long strings into "start ... end".
Definition Strings.cpp:52
T extractToValueVector(const std::string &strvalue)
void toValue(const std::string &strvalue, T &value)
std::string toString(const T &value)
Convert values to strings.
std::vector< std::string > determineAllowedValues(const T &, const IValidator &validator)
void addingOperator(T &lhs, const T &rhs)
int findSize(const T &)
Specialization for any type, should be appropriate for properties with a single value.
MANTID_KERNEL_DLL::Json::Value encodeAsJson(const OptionalBool &)
Encode an OptionalBool as a Json::Value.
std::shared_ptr< IValidator > IValidator_sptr
A shared_ptr to an IValidator.
Definition IValidator.h:26
std::string toPrettyString(const T &value, size_t maxLength=0, bool collapseLists=true)
Convert values to pretty strings.
Helper class which provides the Collimation Length for SANS instruments.
STL namespace.