Mantid
Loading...
Searching...
No Matches
PropertyManager.cpp
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 +
7//----------------------------------------------------------------------
8// Includes
9//----------------------------------------------------------------------
11#include "MantidJson/Json.h"
17
18#include <json/json.h>
19
20namespace Mantid::Kernel {
21
22using std::string;
23
24namespace {
25// static logger reference
26Logger g_log("PropertyManager");
27
33const std::string createKey(const std::string &name) {
34 std::string key = name;
35 std::transform(key.begin(), key.end(), key.begin(), toupper);
36 return key;
37}
38} // namespace
39
40const std::string PropertyManager::INVALID_VALUES_SUFFIX = "_invalid_values";
43std::string PropertyManager::getInvalidValuesFilterLogName(const std::string &logName) {
45}
46std::string PropertyManager::getLogNameFromInvalidValuesFilter(const std::string &logName) {
47 std::string retVal = "";
49 retVal = logName.substr(0, logName.size() - PropertyManager::INVALID_VALUES_SUFFIX.size());
50 }
51 return retVal;
52}
53bool PropertyManager::isAnInvalidValuesFilterLog(const std::string &logName) {
55 if (logName.length() >= ending.length()) {
56 return (0 == logName.compare(logName.length() - ending.length(), ending.length(), ending));
57 } else {
58 return false;
59 }
60}
61//-----------------------------------------------------------------------------------------------
63PropertyManager::PropertyManager() : m_properties(), m_orderedProperties() {}
64
65//-----------------------------------------------------------------------------------------------
69 : m_properties(), m_orderedProperties(other.m_orderedProperties.size()) {
70 // We need to do a deep copy of the property pointers here
71 for (unsigned int i = 0; i < m_orderedProperties.size(); ++i) {
72 auto p = std::unique_ptr<Property>(other.m_orderedProperties[i]->clone());
73 this->m_orderedProperties[i] = p.get();
74 this->m_properties[createKey(p->name())] = std::move(p);
75 }
76}
77
78//-----------------------------------------------------------------------------------------------
83 // We need to do a deep copy here
84 if (this != &other) {
85 this->m_properties.clear();
86 this->m_orderedProperties.resize(other.m_orderedProperties.size());
87 for (unsigned int i = 0; i < m_orderedProperties.size(); ++i) {
88 auto p = std::unique_ptr<Property>(other.m_orderedProperties[i]->clone());
89 this->m_orderedProperties[i] = p.get();
90 this->m_properties[createKey(p->name())] = std::move(p);
91 }
92 }
93 return *this;
94}
95
96//-----------------------------------------------------------------------------------------------
99
100//-----------------------------------------------------------------------------------------------
107 // Iterate through all properties on the RHS
108 PropertyMap::const_iterator it;
109 for (it = rhs.m_properties.begin(); it != rhs.m_properties.end(); ++it) {
110 // The name on the rhs
111 string rhs_name = it->first;
112 try {
113 Property *lhs_prop = this->getPointerToProperty(rhs_name);
114 // Use the property's += operator to add THAT. Isn't abstraction fun?!
115 (*lhs_prop) += it->second.get();
116 } catch (Exception::NotFoundError &) {
117 // The property isnt on the lhs.
118 // Let's copy it
119 auto copy = std::unique_ptr<Property>(it->second->clone());
120 // And we add a copy of that property to *this
121 this->declareProperty(std::move(copy), "");
122 }
123 }
124
125 return *this;
126}
127
128//-----------------------------------------------------------------------------------------------
139void PropertyManager::filterByTime(const Types::Core::DateAndTime &start, const Types::Core::DateAndTime &stop) {
140 // Iterate through all properties
141 PropertyMap::const_iterator it;
142 for (it = this->m_properties.begin(); it != this->m_properties.end(); ++it) {
143 // Filter out the property
144 auto prop = it->second.get();
145 prop->filterByTime(start, stop);
146 }
147}
148
149//-----------------------------------------------------------------------------------------------
158void PropertyManager::splitByTime(std::vector<SplittingInterval> &splitter,
159 std::vector<PropertyManager *> outputs) const {
160 size_t n = outputs.size();
161
162 // Iterate through all properties
163 PropertyMap::const_iterator it;
164 for (it = this->m_properties.begin(); it != this->m_properties.end(); ++it) {
165 // Filter out the property
166 Property *prop = it->second.get();
167
168 // Make a vector of the output properties contained in the other property
169 // managers.
170 // NULL if it was not found.
171 std::vector<Property *> output_properties;
172 for (size_t i = 0; i < n; i++) {
173 if (outputs[i])
174 output_properties.emplace_back(outputs[i]->getPointerToPropertyOrNull(prop->name()));
175 else
176 output_properties.emplace_back(nullptr);
177 }
178
179 // Now the property does the splitting.
180 bool isProtonCharge = prop->name() == "proton_charge";
181 prop->splitByTime(splitter, output_properties, isProtonCharge);
182
183 } // for each property
184}
185
186//-----------------------------------------------------------------------------------------------
196 const std::vector<std::string> &excludedFromFiltering) {
197 for (auto &orderedProperty : m_orderedProperties) {
198 if (std::find(excludedFromFiltering.cbegin(), excludedFromFiltering.cend(), orderedProperty->name()) !=
199 excludedFromFiltering.cend()) {
200 // this log should be excluded from filtering
201 continue;
202 }
203
204 Property *currentProp = orderedProperty;
205 if (auto doubleSeries = dynamic_cast<TimeSeriesProperty<double> *>(currentProp)) {
206 // don't filter the invalid values filters
208 break;
209 std::unique_ptr<Property> filtered(nullptr);
211 // add the filter to the passed in filters
212 auto logFilter = std::make_unique<LogFilter>(filter);
214 auto tspFilterProp = dynamic_cast<TimeSeriesProperty<bool> *>(filterProp);
215 if (!tspFilterProp)
216 break;
217 logFilter->addFilter(*tspFilterProp);
218
219 filtered = std::make_unique<FilteredTimeSeriesProperty<double>>(doubleSeries, *logFilter->filter());
220 } else {
221 filtered = std::make_unique<FilteredTimeSeriesProperty<double>>(doubleSeries, filter);
222 }
223 orderedProperty = filtered.get();
224 // Now replace in the map
225 this->m_properties[createKey(currentProp->name())] = std::move(filtered);
226 }
227 }
228}
229
230//-----------------------------------------------------------------------------------------------
238void PropertyManager::declareProperty(std::unique_ptr<Property> p, const std::string &doc) {
239 p->setDocumentation(doc);
240
241 const std::string key = createKey(p->name());
242 auto existing = m_properties.find(key);
243 if (existing == m_properties.end()) {
244 m_orderedProperties.emplace_back(p.get());
245 m_properties[key] = std::move(p);
246 } else {
247 // Don't error if this is actually the same property object!
248 if (existing->second != p) {
249 throw Exception::ExistsError("Property with given name already exists", key);
250 }
251 }
252}
253
259void PropertyManager::declareOrReplaceProperty(std::unique_ptr<Property> p, const std::string &doc) {
260 p->setDocumentation(doc);
261
262 const std::string key = createKey(p->name());
263 auto existing = m_properties.find(key);
264 if (existing != std::end(m_properties)) {
265 // replace it in the same position
266 auto oldPropPtr = existing->second.get();
267 auto ordereredPropPos = std::find(std::begin(m_orderedProperties), std::end(m_orderedProperties), oldPropPtr);
268 // if the property exists it should be guaranteed to be in the ordered list
269 // by declareProperty
270 assert(ordereredPropPos != std::end(m_orderedProperties));
271 *ordereredPropPos = p.get();
272 } else {
273 m_orderedProperties.emplace_back(p.get());
274 }
275 m_properties[key] = std::move(p);
276}
277
281 for (auto &prop : getProperties()) {
282 if (!prop->isDefault())
283 prop->setValue(prop->getDefault());
284 }
285}
286
287//-----------------------------------------------------------------------------------------------
299void PropertyManager::setProperties(const std::string &propertiesJson,
300 const std::unordered_set<std::string> &ignoreProperties, bool createMissing) {
301 setProperties(propertiesJson, this, ignoreProperties, createMissing);
302}
303//-----------------------------------------------------------------------------------------------
317void PropertyManager::setProperties(const std::string &propertiesJson, IPropertyManager *targetPropertyManager,
318 const std::unordered_set<std::string> &ignoreProperties, bool createMissing) {
319 ::Json::Value jsonValue;
320
321 if (Mantid::JsonHelpers::parse(propertiesJson, &jsonValue)) {
322 setProperties(jsonValue, targetPropertyManager, ignoreProperties, createMissing);
323 } else {
324 throw std::invalid_argument("propertiesArray was not valid json");
325 }
326}
327//-----------------------------------------------------------------------------------------------
335void PropertyManager::setProperties(const ::Json::Value &jsonValue,
336 const std::unordered_set<std::string> &ignoreProperties, bool createMissing) {
337 setProperties(jsonValue, this, ignoreProperties, createMissing);
338}
339
340//-----------------------------------------------------------------------------------------------
350void PropertyManager::setProperties(const ::Json::Value &jsonValue, IPropertyManager *targetPropertyManager,
351 const std::unordered_set<std::string> &ignoreProperties, bool createMissing) {
352 if (jsonValue.type() != ::Json::ValueType::objectValue)
353 return;
354
355 // Some algorithms require Filename to be set first do that here
356 static const std::string propFilename = "Filename";
357 const ::Json::Value &filenameValue = jsonValue[propFilename];
358 if (!filenameValue.isNull()) {
359 const std::string value = filenameValue.asString();
360 // Set it
361 targetPropertyManager->setPropertyValue(propFilename, value);
362 }
363 const auto memberNames = jsonValue.getMemberNames();
364 for (::Json::ArrayIndex i = 0; i < jsonValue.size(); i++) {
365 const auto &propName = memberNames[i];
366 if ((propFilename == propName) || (ignoreProperties.find(propName) != ignoreProperties.end())) {
367 continue;
368 }
369 const ::Json::Value &propValue = jsonValue[propName];
370 if (createMissing) {
371 targetPropertyManager->declareOrReplaceProperty(decodeAsProperty(propName, propValue));
372 } else {
373 targetPropertyManager->setPropertyValueFromJson(propName, propValue);
374 }
375 }
376}
377
384void PropertyManager::setPropertiesWithString(const std::string &propertiesString,
385 const std::unordered_set<std::string> &ignoreProperties) {
386 if (propertiesString.empty()) {
387 return;
388 }
389 auto firstSymbol = propertiesString.find_first_not_of(" \n\t");
390 if (firstSymbol == std::string::npos) {
391 return;
392 }
393 if (propertiesString[firstSymbol] == '{') {
394 setPropertiesWithJSONString(propertiesString, ignoreProperties);
395 } else {
396 setPropertiesWithSimpleString(propertiesString, ignoreProperties);
397 }
398}
399
405void PropertyManager::setPropertiesWithJSONString(const std::string &propertiesString,
406 const std::unordered_set<std::string> &ignoreProperties) {
407 ::Json::Value propertyJson;
408
409 if (Mantid::JsonHelpers::parse(propertiesString, &propertyJson)) {
410 setProperties(propertyJson, ignoreProperties);
411 } else {
412 throw std::invalid_argument("Could not parse JSON string when trying to set a property from: " + propertiesString);
413 }
414}
415
422void PropertyManager::setPropertiesWithSimpleString(const std::string &propertiesString,
423 const std::unordered_set<std::string> &ignoreProperties) {
424 ::Json::Value propertyJson;
425 // Split up comma-separated properties
427
428 boost::char_separator<char> sep(";");
429 tokenizer propPairs(propertiesString, ";", Mantid::Kernel::StringTokenizer::TOK_TRIM);
430 // Iterate over the properties
431 for (const auto &pair : propPairs) {
432 size_t n = pair.find('=');
433 if (n != std::string::npos) {
434 // Normal "PropertyName=value" string.
435 std::string propName;
436 std::string value;
437
438 // Extract the value string
439 if (n < pair.size() - 1) {
440 propName = pair.substr(0, n);
441 value = pair.substr(n + 1, pair.size() - n - 1);
442 } else {
443 // String is "PropertyName="
444 propName = pair.substr(0, n);
445 value = "";
446 }
447 // Set it
448 propertyJson[propName] = value;
449 }
450 }
451 setProperties(propertyJson, ignoreProperties);
452}
453
454//-----------------------------------------------------------------------------------------------
463void PropertyManager::setPropertyValue(const std::string &name, const std::string &value) {
464 auto *prop = getPointerToProperty(name);
465 auto helpMsg = prop->setValue(value);
466 afterPropertySet(name);
467 if (!helpMsg.empty()) {
468 helpMsg = "Invalid value for property " + prop->name() + " (" + prop->type() + ") from string \"" + value +
469 "\": " + helpMsg;
470 throw std::invalid_argument(helpMsg);
471 }
472}
473
481void PropertyManager::setPropertyValueFromJson(const std::string &name, const Json::Value &value) {
482 auto *prop = getPointerToProperty(name);
483 auto helpMsg = prop->setValueFromJson(value);
484 afterPropertySet(name);
485 if (!helpMsg.empty()) {
486 helpMsg = "Invalid value for property " + prop->name() + " (" + prop->type() + ") from Json \"" +
487 value.toStyledString() + "\": " + helpMsg;
488 throw std::invalid_argument(helpMsg);
489 }
490}
491
492//-----------------------------------------------------------------------------------------------
501void PropertyManager::setPropertyOrdinal(const int &index, const std::string &value) {
502 Property *p = getPointerToPropertyOrdinal(index); // throws runtime_error if property not in vector
503 std::string errorMsg = p->setValue(value);
504 this->afterPropertySet(p->name());
505 if (!errorMsg.empty()) {
506 errorMsg = "Invalid value for property " + p->name() + " (" + p->type() + ") \"" + value + "\" : " + errorMsg;
507 throw std::invalid_argument(errorMsg);
508 }
509}
510
511//-----------------------------------------------------------------------------------------------
517bool PropertyManager::existsProperty(const std::string &name) const {
518 const std::string key = createKey(name);
519 auto it = m_properties.find(key);
520 return (it != m_properties.end());
521}
522
523//-----------------------------------------------------------------------------------------------
528 bool allValid = true;
529 for (const auto &property : m_properties) {
530 // check for errors in each property
531 std::string error = property.second->isValid();
532 //"" means no error
533 if (!error.empty()) {
534 g_log.error() << "Property \"" << property.first << "\" is not set to a valid value: \"" << error << "\".\n";
535 allValid = false;
536 }
537 }
538 return allValid;
539}
540
541//-----------------------------------------------------------------------------------------------
547
548//-----------------------------------------------------------------------------------------------
554std::string PropertyManager::getPropertyValue(const std::string &name) const {
555 Property *p = getPointerToProperty(name); // throws NotFoundError if property not in vector
556 return p->value();
557}
558
559//-----------------------------------------------------------------------------------------------
567std::string PropertyManager::asString(bool withDefaultValues) const {
568 Json::StreamWriterBuilder builder;
569 builder.settings_["indentation"] = "";
570 const string output = Json::writeString(builder, asJson(withDefaultValues));
571
572 return output;
573}
574
575//-----------------------------------------------------------------------------------------------
581::Json::Value PropertyManager::asJson(bool withDefaultValues) const {
582 ::Json::Value jsonMap;
583 const auto count = static_cast<int>(propertyCount());
584 for (int i = 0; i < count; ++i) {
586 bool is_enabled = true;
587 if (p->getSettings()) {
588 is_enabled = p->getSettings()->isEnabled(this);
589 }
590 if (p->isValueSerializable() && (withDefaultValues || !p->isDefault()) && is_enabled) {
591 jsonMap[p->name()] = p->valueAsJson();
592 }
593 }
594
595 return jsonMap;
596}
597
599 if (other.m_properties.size() != m_properties.size())
600 return false;
601 for (const auto &[key, value] : m_properties) {
602 if (other.m_properties.count(key) != 1)
603 return false;
604 if (*other.m_properties.at(key) != *value)
605 return false;
606 }
607 return true;
608}
609
610bool PropertyManager::operator!=(const PropertyManager &other) const { return !this->operator==(other); }
611
612//-----------------------------------------------------------------------------------------------
618Property *PropertyManager::getPointerToProperty(const std::string &name) const {
619 const std::string key = createKey(name);
620 auto it = m_properties.find(key);
621 if (it != m_properties.end()) {
622 return it->second.get();
623 }
624 throw Exception::NotFoundError("Unknown property", name);
625}
626
627//-----------------------------------------------------------------------------------------------
633 const std::string key = createKey(name);
634 auto it = m_properties.find(key);
635 if (it != m_properties.end()) {
636 return it->second.get();
637 }
638 return nullptr;
639}
640
641//-----------------------------------------------------------------------------------------------
648
649 if (index < static_cast<int>(m_orderedProperties.size())) {
651 }
652 throw std::runtime_error("Property index too high");
653}
654
655//-----------------------------------------------------------------------------------------------
660const std::vector<Property *> &PropertyManager::getProperties() const { return m_orderedProperties; }
661
662//-----------------------------------------------------------------------------------------------
667std::vector<std::string> PropertyManager::getDeclaredPropertyNames() const noexcept {
668 std::vector<std::string> names;
669 const auto &props = getProperties();
670 names.reserve(props.size());
671 std::transform(props.cbegin(), props.cend(), std::back_inserter(names),
672 [](auto &propPtr) { return propPtr->name(); });
673 return names;
674}
675
676//-----------------------------------------------------------------------------------------------
694 return TypedValue(*this, name);
695}
696
697//-----------------------------------------------------------------------------------------------
702void PropertyManager::removeProperty(const std::string &name, const bool delproperty) {
703 if (existsProperty(name)) {
704 // remove it
705 Property *prop = getPointerToProperty(name);
706 const std::string key = createKey(name);
707 m_properties.erase(key);
708 std::vector<Property *>::iterator itr;
709 itr = find(m_orderedProperties.begin(), m_orderedProperties.end(), prop);
710 m_orderedProperties.erase(itr);
711 (void)delproperty; // not used
712 }
713}
714
720std::unique_ptr<Property> PropertyManager::takeProperty(const size_t index) {
721 try {
722 auto property = m_orderedProperties[index];
723 const std::string key = createKey(property->name());
724 auto propertyPtr = std::move(m_properties[key]);
725 m_properties.erase(key);
727 return propertyPtr;
728 } catch (const std::out_of_range &) {
729 return NULL;
730 }
731}
732
733//-----------------------------------------------------------------------------------------------
738 m_orderedProperties.clear();
739 m_properties.clear();
740}
741
742//-----------------------------------------------------------------------------------------------
748Json::Value encodeAsJson(const PropertyManager &propMgr) { return propMgr.asJson(true); }
749
750} // namespace Mantid::Kernel
const std::vector< double > & rhs
double value
The value of the point.
Definition: FitMW.cpp:51
double error
Definition: IndexPeaks.cpp:133
std::map< DeltaEMode::Type, std::string > index
Definition: DeltaEMode.cpp:19
int count
counter
Definition: Matrix.cpp:37
Exception for when an item is already in a collection.
Definition: Exception.h:164
Exception for when an item is not found in a collection.
Definition: Exception.h:145
Interface to PropertyManager.
virtual void setPropertyValue(const std::string &name, const std::string &value)=0
Sets property value from a string.
virtual void declareOrReplaceProperty(std::unique_ptr< Property > p, const std::string &doc="")=0
Function to declare properties (i.e. store them)
virtual void afterPropertySet(const std::string &)
Override this method to perform a custom action right after a property was set.
virtual void setPropertyValueFromJson(const std::string &name, const Json::Value &value)=0
Sets property value from a Json::Value.
virtual bool isEnabled(const IPropertyManager *algo) const
Is the property to be shown as "enabled" in the GUI.
void error(const std::string &msg)
Logs at error level.
Definition: Logger.cpp:77
Property manager helper class.
bool operator!=(const PropertyManager &other) const
void setPropertyValue(const std::string &name, const std::string &value) override
Set the value of a property by string N.B.
bool validateProperties() const override
Validates all the properties in the collection.
void removeProperty(const std::string &name, const bool delproperty=true) override
removes the property from properties map
void setPropertyOrdinal(const int &index, const std::string &value) override
Set the value of a property by an index N.B.
void declareOrReplaceProperty(std::unique_ptr< Property > p, const std::string &doc="") override
Add or replace a property in the list of managed properties.
size_t propertyCount() const override
Count the number of properties under management.
PropertyManager & operator+=(const PropertyManager &rhs)
Addition operator.
PropertyManager()
Default constructor.
void resetProperties() override
Reset property values back to initial values (blank or default values)
void filterByProperty(const TimeSeriesProperty< bool > &filter, const std::vector< std::string > &excludedFromFiltering=std::vector< std::string >()) override
Filter the managed properties by the given boolean property mask.
Property * getPointerToProperty(const std::string &name) const override
Get a property by name.
bool existsProperty(const std::string &name) const override
Checks whether the named property is already in the list of managed property.
void setProperties(const std::string &propertiesJson, const std::unordered_set< std::string > &ignoreProperties=std::unordered_set< std::string >(), bool createMissing=false) override
Set the ordered list of properties by one string of values, separated by semicolons.
void setPropertiesWithString(const std::string &propertiesString, const std::unordered_set< std::string > &ignoreProperties=std::unordered_set< std::string >()) override
Sets all the declared properties from a string.
PropertyMap m_properties
The properties under management.
std::string asString(bool withDefaultValues=false) const override
Return the property manager serialized as a string.
void setPropertiesWithJSONString(const std::string &propertiesString, const std::unordered_set< std::string > &ignoreProperties)
Sets all the declared properties from a string.
static bool isAnInvalidValuesFilterLog(const std::string &logName)
void setPropertiesWithSimpleString(const std::string &propertiesString, const std::unordered_set< std::string > &ignoreProperties)
Sets all the declared properties from a string.
static std::string getInvalidValuesFilterLogName(const std::string &logName)
Gets the correct log name for the matching invalid values log for a given log name.
std::string getPropertyValue(const std::string &name) const override
Get the value of a property as a string.
std::unique_ptr< Property > takeProperty(const size_t index) override
removes the property from the properties map and returns a pointer to it
void filterByTime(const Types::Core::DateAndTime &start, const Types::Core::DateAndTime &stop) override
Filter out a run by time.
static std::string getLogNameFromInvalidValuesFilter(const std::string &logName)
void clear() override
Clears the whole property map.
Property * getPointerToPropertyOrdinal(const int &index) const override
Get a property by an index.
TypedValue getProperty(const std::string &name) const override
Get the value of a property.
void splitByTime(std::vector< SplittingInterval > &splitter, std::vector< PropertyManager * > outputs) const override
Split a run by time (splits the TimeSeriesProperties contained).
::Json::Value asJson(bool withDefaultValues=false) const override
Return the property manager serialized as a json object.
Property * getPointerToPropertyOrNull(const std::string &name) const
Get a property by name.
std::vector< Property * > m_orderedProperties
Stores the order in which the properties were declared.
void declareProperty(std::unique_ptr< Property > p, const std::string &doc="") override
Add a property to the list of managed properties.
PropertyManager & operator=(const PropertyManager &)
Assignment operator - performs a deep copy.
bool operator==(const PropertyManager &other) const
void setPropertyValueFromJson(const std::string &name, const Json::Value &value) override
Set the value of a property by Json::Value.
static const std::string INVALID_VALUES_SUFFIX
const std::vector< Property * > & getProperties() const override
Get the list of managed properties.
virtual ~PropertyManager() override
Virtual destructor.
std::vector< std::string > getDeclaredPropertyNames() const noexcept override
Return the list of declared property names.
Base class for properties.
Definition: Property.h:94
IPropertySettings * getSettings()
Definition: Property.cpp:98
virtual std::string setValue(const std::string &)=0
Set the value of the property via a string.
virtual bool isDefault() const =0
Overriden function that returns if property has the same value that it was initialised with,...
const std::string & name() const
Get the property's name.
Definition: Property.cpp:60
const std::string type() const
Returns the type of the property as a string.
Definition: Property.cpp:76
virtual void splitByTime(std::vector< SplittingInterval > &splitter, std::vector< Property * > outputs, bool isProtonCharge=true) const
Split a property by time.
Definition: Property.cpp:208
virtual Json::Value valueAsJson() const =0
Returns the value of the property as a Json::Value.
virtual std::string value() const =0
Returns the value of the property as a string.
virtual bool isValueSerializable() const
Whether the string returned by value() can be used for serialization.
Definition: Property.h:138
@ TOK_TRIM
remove leading and trailing whitespace from tokens
A specialised Property class for holding a series of time-value pairs.
MANTID_KERNEL_DLL std::unique_ptr< Property > decodeAsProperty(const std::string &name, const Json::Value &value)
Attempt to create a Property of the most appropriate type from a string name and Json value object.
MANTID_KERNEL_DLL::Json::Value encodeAsJson(const OptionalBool &)
Encode an OptionalBool as a Json::Value.
Utility class that enables the getProperty() method to effectively be templated on the return type.