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;
}
}
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());
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;
}
}
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
}
Steve Williams
committed
* @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.
Freddie Akeroyd
committed
* @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 )
Russell Taylor
committed
98
99
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
// 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++;
Freddie Akeroyd
committed
}
/** Set the value of a property by string
* 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
/** Set the value of a property by an index
* 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
Steve Williams
committed
* @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;
}
}
/** Validates all the properties in the collection
* @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
/** 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 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
/** Get a property by name
* @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
/** Get a property by an index
* @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
/** Get the list of managed properties.
* 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);
Russell Taylor
committed
delete prop;