diff --git a/Code/Mantid/Kernel/doc/PropertyManager.txt b/Code/Mantid/Kernel/doc/PropertyManager.txt new file mode 100644 index 0000000000000000000000000000000000000000..bf9187749071b17f5ad4282f057910b38d104da1 --- /dev/null +++ b/Code/Mantid/Kernel/doc/PropertyManager.txt @@ -0,0 +1,23 @@ +RJT, 20/11/07 +============= + +Regarding the IProperty interface methods.... + + setProperty (const Property &p) - don't really understand the function of this method. + It uses the Gaudi Property assign() method. + setProperty (const std::string &s) - this uses the output of Gaudi's Property::fillStream method where the property is + represented as 'name':value. I haven't included that method at present, so + have left out this one as well. + + setProperty (const std::string &n, const std::string &v) - Kept, but return type changed to void + getProperty (Property *p) const -> renamed checkProperty + getProperty (const std::string &name) const - Kept + getProperty (const std::string &n, std::string &v) -> renamed getPropertyValue and string value is the return type + std::vector< Property * >& getProperties () const - Kept + + +There's no concept of 'mandatoryness' in there yet. + +The Gaudi class has 'remote properties' - I don't. + +Our property manager class owns all its properties. \ No newline at end of file diff --git a/Code/Mantid/Kernel/inc/PropertyManager.h b/Code/Mantid/Kernel/inc/PropertyManager.h new file mode 100644 index 0000000000000000000000000000000000000000..5c75a56403a5ea7dafe8012deaae6ff6d33a9a98 --- /dev/null +++ b/Code/Mantid/Kernel/inc/PropertyManager.h @@ -0,0 +1,78 @@ +#ifndef MANTID_KERNEL_PROPERTYMANAGER_H_ +#define MANTID_KERNEL_PROPERTYMANAGER_H_ + +//---------------------------------------------------------------------- +// Includes +//---------------------------------------------------------------------- +#include "IProperty.h" +#include <vector> + +namespace Mantid +{ +namespace Kernel +{ +//---------------------------------------------------------------------- +// Forward declaration +//---------------------------------------------------------------------- +class Property; + +/** @class PropertyManager PropertyManager.h Kernel/PropertyManager.h + + Property manager helper class. + This class is used by algorithms and services for helping to manage their own set of properties. + It implements the IProperty interface. + + @author Russell Taylor, Tessella Support Services plc + @author Based on the Gaudi class PropertyMgr (see http://proj-gaudi.web.cern.ch/proj-gaudi/) + @date 20/11/2007 + + Copyright © 2007 STFC Rutherford Appleton Laboratories + + This file is part of Mantid. + + Mantid is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + Mantid is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + + File change history is stored at: <https://svn.mantidproject.org/mantid/trunk/Code/Mantid>. + Code Documentation is available at: <http://doxygen.mantidproject.org> +*/ +class DLLExport PropertyManager //: public IProperty +{ +public: + PropertyManager(); + virtual ~PropertyManager(); + + // Overloaded functions to declare properties (i.e. store them) + void declareProperty( Property *p ); + void declareProperty( const std::string &name, int value, const std::string &doc="" ); + void declareProperty( const std::string &name, double value, const std::string &doc="" ); + void declareProperty( const std::string &name, std::string value, const std::string &doc="" ); + + // IProperty methods + void setProperty( const std::string &name, const std::string &value ); + bool checkProperty( Property *p ) const; + std::string getPropertyValue( const std::string &name ) const; + Property* getProperty( std::string name ) const; + const std::vector< Property* >& getProperties() const; + +private: + bool checkProperty( const std::string& name) const; + + /// The properties under management + std::vector<Property*> m_properties; +}; + +} // namespace Kernel +} // namespace Mantid + +#endif /*MANTID_KERNEL_PROPERTYMANAGER_H_*/ diff --git a/Code/Mantid/Kernel/inc/PropertyWithValue.h b/Code/Mantid/Kernel/inc/PropertyWithValue.h index 13015e3b9b244db84b90d84092461bf1e4d25c08..64ccd73a39519f52ad1b0689e5d70eb280543062 100644 --- a/Code/Mantid/Kernel/inc/PropertyWithValue.h +++ b/Code/Mantid/Kernel/inc/PropertyWithValue.h @@ -128,7 +128,7 @@ public: return m_value; } - /** Allows you to get the value of the property simply by typing its name. (e.g. myProperty) + /** Allows you to get the value of the property simply by typing its name. * Means you can use an expression like: int i = myProperty; */ operator const TYPE& () const diff --git a/Code/Mantid/Kernel/src/PropertyManager.cpp b/Code/Mantid/Kernel/src/PropertyManager.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8ce78c887fe64f02edf9c077f1a98ed349795044 --- /dev/null +++ b/Code/Mantid/Kernel/src/PropertyManager.cpp @@ -0,0 +1,175 @@ +#include "PropertyManager.h" +#include "PropertyWithValue.h" +#include "Exception.h" + +namespace Mantid +{ +namespace Kernel +{ + +/// Default constructor +PropertyManager::PropertyManager() : + m_properties() +{ +} + +/// Virtual destructor +PropertyManager::~PropertyManager() +{ + for ( std::vector<Property*>::const_iterator it = m_properties.begin() ; it != m_properties.end() ; ++it ) + { + delete (*it); + } +} + +/** Add a property to the list of managed properties + * @param p The property object to add + */ +void PropertyManager::declareProperty( Property *p ) +{ + if ( ! checkProperty( p ) ) + { + m_properties.push_back(p); + } + else + { + throw Exception::ExistsError("Property with given name already exists", p->name() ); + } +} + +/** Add an integer property to the list of managed properties + * @param name The name to assign to the property + * @param value The initial value to assign to the property + * @param doc The (optional) documentation string + */ +void PropertyManager::declareProperty( const std::string &name, int value, const std::string &doc ) +{ + if ( ! checkProperty( name ) ) + { + Property *p = new PropertyWithValue<int>(name, value); + p->setDocumentation(doc); + m_properties.push_back(p); + } + else + { + throw Exception::ExistsError("Property with given name already exists", name ); + } +} + +/** Add a double property to the list of managed properties + * @param name The name to assign to the property + * @param value The initial value to assign to the property + * @param doc The (optional) documentation string + */ +void PropertyManager::declareProperty( const std::string &name, double value, const std::string &doc ) +{ + if ( ! checkProperty( name ) ) + { + Property *p = new PropertyWithValue<double>(name, value); + p->setDocumentation(doc); + m_properties.push_back(p); + } + else + { + throw Exception::ExistsError("Property with given name already exists", name ); + } +} + +/** Add a string property to the list of managed properties + * @param name The name to assign to the property + * @param value The initial value to assign to the property + * @param doc The (optional) documentation string + */ +void PropertyManager::declareProperty( const std::string &name, std::string value, const std::string &doc ) +{ + if ( ! checkProperty( name ) ) + { + Property *p = new PropertyWithValue<std::string>(name, value); + p->setDocumentation(doc); + m_properties.push_back(p); + } + else + { + throw Exception::ExistsError("Property with given name already exists", name ); +} +} + +/** Set the value of a property by string + * @param name The name of the property (case insensitive) + * @param value The value to assign to the property + * @throw NotFoundError if the named property is unknown + */ +void PropertyManager::setProperty( const std::string &name, const std::string &value ) +{ + Property *p = getProperty(name); // throws NotFoundError if property not in vector + bool success = p->setValue(value); + if ( !success ) throw std::invalid_argument("Invalid value for this property"); +} + +/** Check whether a given property is already in the list of managed properties. + * Note that the check is performed purely on the name (not on, for example, the type) + * and is case insensitive. + * @param p The property to check + * @return True if the property is already stored + */ +bool PropertyManager::checkProperty( Property *p ) const +{ + return checkProperty( p->name() ); +} + +/** Checks whether the named property is already in the list of managed property. + * @param p The name of the property (case insensitive) + * @return True is the property is already stored + */ +bool PropertyManager::checkProperty( const std::string& name ) const +{ + try { + getProperty(name); + return true; + } catch (Exception::NotFoundError e) { + return false; + } +} + +/** Get the value of a property as a string + * @param name The name of the property (case insensitive) + * @return The value of the named property + * @throw NotFoundError if the named property is unknown + */ +std::string PropertyManager::getPropertyValue( const std::string &name ) const +{ + Property *p = getProperty(name); // throws NotFoundError if property not in vector + return p->value(); +} + +/** Get a property by name + * @param name The name of the property (case insensitive) + * @return A pointer to the named property + * @throw NotFoundError if the named property is unknown + */ +Property* PropertyManager::getProperty( std::string name ) const +{ + /// TODO Re-work to be more efficient + for ( std::vector<Property*>::const_iterator it = m_properties.begin() ; it != m_properties.end() ; ++it ) + { + std::string n = (*it)->name(); + std::transform(n.begin(), n.end(), n.begin(), toupper); + std::transform(name.begin(), name.end(), name.begin(), toupper); + if ( ! name.compare(n) ) + { + return *it; + } + } + throw Exception::NotFoundError("Unable to retrieve property", name); +} + +/** Get the list of managed properties + * @return A vector holding pointers to the list of properties + */ +const std::vector< Property* >& PropertyManager::getProperties() const +{ + return m_properties; +} + +} // namespace Kernel +} // namespace Mantid diff --git a/Code/Mantid/Kernel/test/PropertyManagerTest.h b/Code/Mantid/Kernel/test/PropertyManagerTest.h new file mode 100644 index 0000000000000000000000000000000000000000..c6f9c846255c0582133aa7385f3c1a269b6303d3 --- /dev/null +++ b/Code/Mantid/Kernel/test/PropertyManagerTest.h @@ -0,0 +1,122 @@ +#ifndef PROPERTYMANAGERTEST_H_ +#define PROPERTYMANAGERTEST_H_ + +#include <cxxtest/TestSuite.h> + +#include "../inc/PropertyManager.h" +#include "../inc/PropertyWithValue.h" +#include <iostream> + +using namespace Mantid::Kernel; + +class PropertyManagerTest : public CxxTest::TestSuite +{ +public: + PropertyManagerTest() + { + Property *p = new PropertyWithValue<int>("aProp",1); + manager.declareProperty(p); + } + + void testConstructor() + { + PropertyManager mgr; + std::vector<Property*> props = mgr.getProperties(); + TS_ASSERT( props.empty() ) + } + + void testdeclareProperty_pointer() + { + PropertyManager mgr; + Property *p = new PropertyWithValue<double>("myProp", 9.99); + TS_ASSERT_THROWS_NOTHING( mgr.declareProperty(p) ) + TS_ASSERT( mgr.checkProperty(p) ) + TS_ASSERT( ! mgr.getPropertyValue("myProp").compare("9.99") ) + + TS_ASSERT_THROWS( mgr.declareProperty(p), Exception::ExistsError ) + } + + void testdeclareProperty_int() + { + PropertyManager mgr; + TS_ASSERT_THROWS_NOTHING( mgr.declareProperty("myProp", 1, "hello") ) + TS_ASSERT( ! mgr.getPropertyValue("myProp").compare("1") ) + Property *p = mgr.getProperty("myProp"); + TS_ASSERT( ! p->documentation().compare("hello") ) + + TS_ASSERT_THROWS( mgr.declareProperty("MYPROP", 5), Exception::ExistsError ) + } + + void testdeclareProperty_double() + { + PropertyManager mgr; + TS_ASSERT_THROWS_NOTHING( mgr.declareProperty("myProp", 9.99, "hello") ) + TS_ASSERT( ! mgr.getPropertyValue("myProp").compare("9.99") ) + Property *p = mgr.getProperty("myProp"); + TS_ASSERT( ! p->documentation().compare("hello") ) + + TS_ASSERT_THROWS( mgr.declareProperty("MYPROP", 5), Exception::ExistsError ) + } + + void testdeclareProperty_string() + { + PropertyManager mgr; + TS_ASSERT_THROWS_NOTHING( mgr.declareProperty("myProp", "theValue", "hello") ) + TS_ASSERT( ! mgr.getPropertyValue("myProp").compare("theValue") ) + Property *p = mgr.getProperty("myProp"); + TS_ASSERT( ! p->documentation().compare("hello") ) + + TS_ASSERT_THROWS( mgr.declareProperty("MYPROP", 5), Exception::ExistsError ) + } + + void testSetProperty() + { + manager.setProperty("APROP","10"); + TS_ASSERT( ! manager.getPropertyValue("aProp").compare("10") ) + manager.setProperty("aProp","1"); + TS_ASSERT_THROWS( manager.setProperty("fhfjsdf","0"), Exception::NotFoundError ) + } + + void testCheckProperty() + { + Property *p = new PropertyWithValue<int>("sjfudh",0); + TS_ASSERT( ! manager.checkProperty(p) ) + Property *pp = new PropertyWithValue<double>("APROP",9.99); + // Note that although the name of the property is the same, the type is different - yet it passes + TS_ASSERT( manager.checkProperty(pp) ) + } + + void testGetPropertyValue() + { + TS_ASSERT( ! manager.getPropertyValue("APROP").compare("1") ) + TS_ASSERT_THROWS( manager.getPropertyValue("sdfshdu"), Exception::NotFoundError ) + } + + void testGetProperty() + { + Property *p = manager.getProperty("APROP"); + TS_ASSERT( p ) + TS_ASSERT( ! p->name().compare("aProp") ) + TS_ASSERT( ! p->value().compare("1") ) + TS_ASSERT( ! p->documentation().compare("") ) + TS_ASSERT( typeid(int) == *p->type_info() ) + + TS_ASSERT_THROWS( manager.getProperty("werhui"), Exception::NotFoundError ) + + } + + void testGetProperties() + { + std::vector<Property*> props = manager.getProperties(); + TS_ASSERT( props.size() == 1 ) + Property *p = props[0]; + TS_ASSERT( ! p->name().compare("aProp") ) + TS_ASSERT( ! p->value().compare("1") ) + } + +private: + PropertyManager manager; + +}; + +#endif /*PROPERTYMANAGERTEST_H_*/