Newer
Older
//----------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------
#include "MantidKernel/PropertyManager.h"
#include "MantidKernel/Exception.h"
// Get a reference to the logger
Logger& PropertyManager::g_log = Logger::get("PropertyManager");
Russell Taylor
committed
m_properties(), m_orderedProperties()
Russell Taylor
committed
Russell Taylor
committed
PropertyManager::PropertyManager(const PropertyManager& other) :
m_properties(), m_orderedProperties(other.m_orderedProperties.size())
{
// We need to do a deep copy of the property pointers here
for (unsigned int i = 0; i < m_orderedProperties.size(); ++i)
{
Property * p = other.m_orderedProperties[i]->clone();
this->m_orderedProperties[i] = p;
this->m_properties[p->name()] = p;
Russell Taylor
committed
}
}
PropertyManager& PropertyManager::operator=(const PropertyManager& other)
{
// We need to do a deep copy here
if ( this != &other )
{
this->m_properties.clear();
this->m_orderedProperties.resize(other.m_orderedProperties.size());
Russell Taylor
committed
for (unsigned int i = 0; i < m_orderedProperties.size(); ++i)
{
Property * p = other.m_orderedProperties[i]->clone();
this->m_orderedProperties[i] = p;
std::string key = p->name();
std::transform(key.begin(), key.end(), key.begin(), toupper);
this->m_properties[key] = p;
Russell Taylor
committed
}
}
return *this;
}
Russell Taylor
committed
/// Virtual destructor
Russell Taylor
committed
for ( PropertyMap::iterator it = m_properties.begin(); it != m_properties.end(); ++it )
Russell Taylor
committed
}
/** Add a property to the list of managed properties
* @param p The property object to add
* @param doc A description of the property that may be displayed to users
* @throw Exception::ExistsError if a property with the given name already exists
* @throw std::invalid_argument if the property declared has an empty name.
*/
Steve Williams
committed
void PropertyManager::declareProperty( Property *p, const std::string &doc )
{
// Get the name of the property and don't permit empty names
std::string key = p->name();
throw std::invalid_argument("An empty property name is not permitted");
}
std::transform(key.begin(), key.end(), key.begin(), toupper);
if ( m_properties.insert(PropertyMap::value_type(key, p)).second)
{
m_orderedProperties.push_back(p);
}
else
{
// Don't delete if this is actually the same property object!!!
if ( m_properties.find(key)->second != p ) delete p;
throw Exception::ExistsError( "Property with given name already exists", key );
Steve Williams
committed
p->setDocumentation(doc);
}
/** Set the ordered list of properties by one string of values.
* @param propertiesArray The list of property values
* @throws invalid_argument if error in parameters
*/
// Care will certainly be required in the calling of this function or it could all go horribly wrong!
Freddie Akeroyd
committed
void PropertyManager::setProperties( const std::string &propertiesArray )
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// Split up comma-separated properties
typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
boost::char_separator<char> sep(";");
tokenizer propPairs(propertiesArray, sep);
int index=0;
// Iterate over the properties
for (tokenizer::iterator it = propPairs.begin(); it != propPairs.end(); ++it)
{
boost::char_separator<char> sep2("=");
tokenizer properties(*it,sep2);
std::vector<std::string> property(properties.begin(), properties.end());
// Call the appropriate setProperty method on the algorithm
if ( property.size() == 2)
{
setPropertyValue(property[0],property[1]);
}
else if ( property.size() == 1)
{
// This is for a property with no value. Not clear that we will want such a thing.
setPropertyOrdinal(index,property[0]);
}
// Throw if there's a problem with the string
else
{
throw std::invalid_argument("Misformed properties string");
}
index++;
}
* N.B. bool properties must be set using 1/0 rather than true/false
* @param name The name of the property (case insensitive)
* @param value The value to assign to the property
* @throw Exception::NotFoundError if the named property is unknown
* @throw std::invalid_argument If the value is not valid for the property given
*/
void PropertyManager::setPropertyValue( const std::string &name, const std::string &value )
{
Property *p = getPointerToProperty(name); // throws NotFoundError if property not in vector
Steve Williams
committed
std::string errorMsg = p->setValue(value);
if ( !errorMsg.empty() )
{
Steve Williams
committed
errorMsg = "Invalid value for property " + p->name() + " (" +p->type() + ") \"" + value
Steve Williams
committed
+ "\": " + errorMsg;
throw std::invalid_argument(errorMsg);
}
Russell Taylor
committed
* N.B. bool properties must be set using 1/0 rather than true/false
* @param index The index of the property to assign
* @param value The value to assign to the property
* @throw std::runtime_error if the property index is too high
* @throw std::invalid_argument If the value is not valid for the property given
*/
void PropertyManager::setPropertyOrdinal( const int& index, const std::string &value )
{
Property *p = getPointerToPropertyOrdinal(index); // throws runtime_error if property not in vector
Steve Williams
committed
std::string errorMsg = p->setValue(value);
if ( !errorMsg.empty() )
{
Steve Williams
committed
errorMsg = "Invalid value for property " + p->name() + " (" +p->type() + ") \"" + value
Steve Williams
committed
+ "\" : " + errorMsg;
Steve Williams
committed
throw std::invalid_argument(errorMsg);
Steve Williams
committed
}
Russell Taylor
committed
/** Checks whether the named property is already in the list of managed property.
* @param name The name of the property (case insensitive)
* @return True if the property is already stored
*/
bool PropertyManager::existsProperty( const std::string& name ) const
{
{
getPointerToProperty(name);
return true;
}
catch (Exception::NotFoundError e)
{
return false;
}
}
* @return True if all properties have a valid value
*/
bool PropertyManager::validateProperties() const
{
bool allValid = true;
for ( PropertyMap::const_iterator it = m_properties.begin(); it != m_properties.end(); ++it )
{
Steve Williams
committed
//check for errors in each property
std::string error = it->second->isValid();
//"" means no error
if ( !error.empty() )
Steve Williams
committed
g_log.error() << "Property \"" << it->first << "\" is not set to a valid value: \"" <<
error << "\"." << std::endl;
Russell Taylor
committed
* @param name The name of the property (case insensitive)
* @return The value of the named property
* @throw Exception::NotFoundError if the named property is unknown
*/
std::string PropertyManager::getPropertyValue( const std::string &name ) const
{
Property *p = getPointerToProperty(name); // throws NotFoundError if property not in vector
return p->value();
}
Russell Taylor
committed
* @param name The name of the property (case insensitive)
* @return A pointer to the named property
* @throw Exception::NotFoundError if the named property is unknown
*/
Property* PropertyManager::getPointerToProperty( const std::string &name ) const
{
std::string ucName = name;
std::transform(ucName.begin(), ucName.end(), ucName.begin(), toupper);
PropertyMap::const_iterator it = m_properties.find(ucName);
if (it != m_properties.end())
{
return it->second;
}
throw Exception::NotFoundError("Unknown property", name);
}
Russell Taylor
committed
* @param index The name of the property (case insensitive)
* @return A pointer to the named property
* @throw std::runtime_error if the property index is too high
*/
Property* PropertyManager::getPointerToPropertyOrdinal( const int& index) const
{
Russell Taylor
committed
if ( index < static_cast<int>(m_orderedProperties.size()) )
{
return m_orderedProperties[index];
}
throw std::runtime_error("Property index too high");
}
Russell Taylor
committed
* The properties will be stored in the order that they were declared.
* @return A vector holding pointers to the list of properties
*/
const std::vector< Property* >& PropertyManager::getProperties() const
{
return m_orderedProperties;
}
/** Get the value of a property. Allows you to assign directly to a variable of the property's type
* (if a supported type).
*
* *** This method does NOT work for assigning to an existing std::string.
* In this case you have to use getPropertyValue() instead.
* Note that you can, though, construct a local string variable by writing,
* e.g. std::string s = getProperty("myProperty"). ***
*
* @param name The name of the property
* @return The value of the property. Will be cast to the desired type (if a supported type).
* @throw std::runtime_error If an attempt is made to assign a property to a different type
* @throw Exception::NotFoundError If the property requested does not exist
*/
PropertyManager::TypedValue PropertyManager::getProperty( const std::string &name ) const
{
return TypedValue(*this, name);
}
Russell Taylor
committed
Russell Taylor
committed
/** Removes the property from properties map.
* @param name name of the property to be removed.
*/
void PropertyManager::removeProperty(const std::string &name)
{
if(existsProperty(name))
{ //remove it
Property* prop=getPointerToProperty(name);
m_properties.erase(name);
std::vector<Property*>::iterator itr;
itr=find(m_orderedProperties.begin(),m_orderedProperties.end(),prop);
m_orderedProperties.erase(itr);
delete prop;
}
}