mirror of
https://github.com/moveit/moveit_task_constructor.git
synced 2025-11-04 14:49:57 +08:00
PropertyMap: different exception types
undeclared undefined type_error
This commit is contained in:
parent
9cd6efe46f
commit
da9cdb5cf6
@ -82,6 +82,15 @@ class Property {
|
||||
}
|
||||
|
||||
public:
|
||||
/// base class for Property exceptions
|
||||
class error;
|
||||
/// exception thrown when accessing an undeclared property
|
||||
class undeclared;
|
||||
/// exception thrown when accessing an undefined property
|
||||
class undefined;
|
||||
/// exception thrown when trying to set a value not matching the declared type
|
||||
class type_error;
|
||||
|
||||
typedef int SourceId;
|
||||
/// function callback used to initialize property value from another PropertyMap
|
||||
typedef std::function<boost::any(const PropertyMap& other)> InitializerFunction;
|
||||
@ -135,6 +144,30 @@ private:
|
||||
};
|
||||
|
||||
|
||||
class Property::error : public std::runtime_error {
|
||||
protected:
|
||||
std::string property_name_;
|
||||
public:
|
||||
explicit error(const std::string& msg) : std::runtime_error(msg) {}
|
||||
const std::string& name() const { return property_name_; }
|
||||
void setName(const std::string& name) { property_name_ = name; }
|
||||
};
|
||||
class Property::undeclared : public Property::error {
|
||||
public:
|
||||
explicit undeclared(const std::string& name);
|
||||
explicit undeclared(const std::string& name, const std::string& msg);
|
||||
};
|
||||
class Property::undefined : public Property::error {
|
||||
public:
|
||||
explicit undefined(const std::string& name);
|
||||
explicit undefined(const std::string& name, const std::string& msg);
|
||||
};
|
||||
class Property::type_error : public Property::error {
|
||||
public:
|
||||
explicit type_error(const std::string& current_type, const std::string& declared_type);
|
||||
};
|
||||
|
||||
|
||||
/** PropertyMap is map of (name, Property) pairs.
|
||||
*
|
||||
* Conveniency methods are provided to setup property initialization for several
|
||||
@ -164,7 +197,9 @@ public:
|
||||
return declare(name, typeid(T), description, default_value, &Property::serialize<T>);
|
||||
}
|
||||
|
||||
/// get the property with given name
|
||||
bool hasProperty(const std::string &name) const;
|
||||
|
||||
/// get the property with given name, throws Property::undeclared for unknown name
|
||||
Property& property(const std::string &name);
|
||||
const Property& property(const std::string &name) const {
|
||||
return const_cast<PropertyMap*>(this)->property(name);
|
||||
@ -190,15 +225,15 @@ public:
|
||||
/// temporarily set the value of a property
|
||||
void setCurrent(const std::string& name, const boost::any& value);
|
||||
|
||||
/// get the value of a property
|
||||
/// Gt the value of a property. Throws undeclared if unknown name
|
||||
const boost::any& get(const std::string& name) const;
|
||||
|
||||
/// Get typed value of property. Throws runtime_error if undefined or bad_any_cast on type mismatch.
|
||||
/// Get typed value of property. Throws undeclared, undefined, or bad_any_cast.
|
||||
template<typename T>
|
||||
const T& get(const std::string& name) const {
|
||||
const boost::any& value = get(name);
|
||||
if (value.empty())
|
||||
throw std::runtime_error(std::string("undefined property: " + name));
|
||||
throw Property::undefined(name);
|
||||
return boost::any_cast<const T&>(value);
|
||||
}
|
||||
/// get typed value of property, using fallback if undefined. Throws bad_any_cast on type mismatch.
|
||||
|
||||
@ -55,16 +55,6 @@ Property::Property(const std::type_index& type_index, const std::string& descrip
|
||||
assert(default_.empty() || std::type_index(default_.type()) == type_index_);
|
||||
}
|
||||
|
||||
namespace {
|
||||
void typeCheck(const boost::any& value, const std::type_index& type_index)
|
||||
{
|
||||
if (std::type_index(value.type()) != type_index) {
|
||||
static boost::format fmt("type (%1%) doesn't match property's declared type (%2%)");
|
||||
throw std::logic_error(boost::str(fmt % value.type().name() % type_index.name()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Property::setValue(const boost::any &value) {
|
||||
setCurrentValue(value);
|
||||
default_ = value_;
|
||||
@ -72,8 +62,9 @@ void Property::setValue(const boost::any &value) {
|
||||
|
||||
void Property::setCurrentValue(const boost::any &value)
|
||||
{
|
||||
if (!value.empty())
|
||||
typeCheck(value, type_index_);
|
||||
if (!value.empty() && std::type_index(value.type()) != type_index_)
|
||||
throw Property::type_error(value.type().name(), type_index_.name());
|
||||
|
||||
value_ = value;
|
||||
if (signaller_)
|
||||
signaller_(this);
|
||||
@ -92,7 +83,7 @@ std::string Property::serialize() const {
|
||||
Property& Property::configureInitFrom(SourceId source, const Property::InitializerFunction &f)
|
||||
{
|
||||
if (source != source_id_ && initializer_)
|
||||
throw std::runtime_error("Property was already configured for initialization from another source id");
|
||||
throw error("Property was already configured for initialization from another source id");
|
||||
|
||||
source_id_ = source;
|
||||
initializer_ = f;
|
||||
@ -117,15 +108,21 @@ Property& PropertyMap::declare(const std::string &name, const std::type_info &ty
|
||||
{
|
||||
auto it_inserted = props_.insert(std::make_pair(name, Property(std::type_index(type), description, default_value, serialize)));
|
||||
if (!it_inserted.second && std::type_index(type) != it_inserted.first->second.type_index_)
|
||||
throw std::logic_error("Property '" + name + "' was already declared with different type.");
|
||||
throw Property::type_error(std::type_index(type).name(), it_inserted.first->second.type_index_.name());
|
||||
return it_inserted.first->second;
|
||||
}
|
||||
|
||||
bool PropertyMap::hasProperty(const std::string& name) const
|
||||
{
|
||||
auto it = props_.find(name);
|
||||
return it != props_.end();
|
||||
}
|
||||
|
||||
Property& PropertyMap::property(const std::string &name)
|
||||
{
|
||||
auto it = props_.find(name);
|
||||
if (it == props_.end())
|
||||
throw std::runtime_error("Undeclared property '" + name + "'");
|
||||
throw Property::undeclared(name);
|
||||
return it->second;
|
||||
}
|
||||
|
||||
@ -142,7 +139,7 @@ void PropertyMap::set<boost::any>(const std::string& name, const boost::any& val
|
||||
auto range = props_.equal_range(name);
|
||||
if (range.first == range.second) { // name is not yet declared
|
||||
if (value.empty())
|
||||
throw std::logic_error("trying to set undeclared property '" + name + "' with NULL value");
|
||||
throw Property::undeclared(name, "trying to set undeclared property '" + name + "' with NULL value");
|
||||
auto it = props_.insert(range.first, std::make_pair(name, Property(value.type(), "", boost::any(),
|
||||
Property::SerializeFunction())));
|
||||
it->second.setValue(value);
|
||||
@ -194,5 +191,32 @@ boost::any fromName(const PropertyMap& other, const std::string& other_name)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Property::undeclared::undeclared(const std::string& name)
|
||||
: undeclared(name, "Undeclared property: '" + name + "'")
|
||||
{}
|
||||
|
||||
Property::undeclared::undeclared(const std::string& name, const std::string& msg)
|
||||
: Property::error(msg)
|
||||
{
|
||||
setName(name);
|
||||
}
|
||||
|
||||
Property::undefined::undefined(const std::string& name)
|
||||
: undefined(name, "Undefined property: '" + name + "'")
|
||||
{}
|
||||
|
||||
Property::undefined::undefined(const std::string& name, const std::string& msg)
|
||||
: Property::error(msg)
|
||||
{
|
||||
setName(name);
|
||||
}
|
||||
|
||||
static boost::format type_error_fmt("type (%1%) doesn't match property's declared type (%2%)");
|
||||
Property::type_error::type_error(const std::string& current_type, const std::string& declared_type)
|
||||
: Property::error(boost::str(type_error_fmt % current_type % declared_type))
|
||||
{}
|
||||
|
||||
|
||||
} // namespace task_constructor
|
||||
} // namespace moveit
|
||||
|
||||
@ -13,9 +13,9 @@ TEST(Property, standard) {
|
||||
|
||||
EXPECT_EQ(props.get<double>("double1"), 1.0);
|
||||
EXPECT_EQ(props.get<double>("double2"), 2.0);
|
||||
EXPECT_THROW(props.get<double>("double3"), std::runtime_error);
|
||||
EXPECT_THROW(props.get<double>("double3"), Property::undeclared);
|
||||
|
||||
EXPECT_THROW(props.get<double>("double4"), std::runtime_error);
|
||||
EXPECT_THROW(props.get<double>("double4"), Property::undefined);
|
||||
EXPECT_FALSE(props.property("double4").defined());
|
||||
EXPECT_EQ(props.get<double>("double4", 0.0), 0.0);
|
||||
|
||||
@ -41,10 +41,10 @@ TEST(Property, redeclare) {
|
||||
|
||||
// avoid second declaration with different type
|
||||
props.declare<double>("double1");
|
||||
EXPECT_THROW(props.declare<long double>("double1"), std::logic_error);
|
||||
EXPECT_THROW(props.declare<long double>("double1"), Property::type_error);
|
||||
|
||||
// types not matching?
|
||||
EXPECT_THROW(props.set("double1", 1), std::logic_error);
|
||||
EXPECT_THROW(props.set("double1", 1), Property::type_error);
|
||||
|
||||
props.set("double1", 3.14);
|
||||
EXPECT_EQ(props.get<double>("double1"), 3.14);
|
||||
@ -108,7 +108,7 @@ TEST_F(InitFromTest, standard) {
|
||||
EXPECT_EQ(slave.get<double>("double1"), 1.0);
|
||||
EXPECT_EQ(slave.get<double>("double2"), 2.0);
|
||||
EXPECT_FALSE(slave.property("double3").defined());
|
||||
EXPECT_THROW(slave.property("double4"), std::runtime_error);
|
||||
EXPECT_THROW(slave.property("double4"), Property::undeclared);
|
||||
}
|
||||
|
||||
TEST_F(InitFromTest, limited) {
|
||||
@ -117,7 +117,7 @@ TEST_F(InitFromTest, limited) {
|
||||
EXPECT_EQ(slave.get<double>("double1"), 1.0);
|
||||
EXPECT_FALSE(slave.property("double2").defined());
|
||||
EXPECT_FALSE(slave.property("double3").defined());
|
||||
EXPECT_THROW(slave.property("double4"), std::runtime_error);
|
||||
EXPECT_THROW(slave.property("double4"), Property::undeclared);
|
||||
}
|
||||
|
||||
TEST_F(InitFromTest, sourceId) {
|
||||
@ -126,7 +126,7 @@ TEST_F(InitFromTest, sourceId) {
|
||||
EXPECT_FALSE(slave.property("double1").defined());
|
||||
EXPECT_FALSE(slave.property("double2").defined());
|
||||
EXPECT_FALSE(slave.property("double3").defined());
|
||||
EXPECT_THROW(slave.property("double4"), std::runtime_error);
|
||||
EXPECT_THROW(slave.property("double4"), Property::undeclared);
|
||||
}
|
||||
|
||||
TEST_F(InitFromTest, multipleSourceIds) {
|
||||
@ -141,7 +141,7 @@ TEST_F(InitFromTest, otherName) {
|
||||
EXPECT_EQ(slave.get<double>("double1"), 2.0);
|
||||
EXPECT_FALSE(slave.property("double2").defined());
|
||||
EXPECT_FALSE(slave.property("double3").defined());
|
||||
EXPECT_THROW(slave.property("double4"), std::runtime_error);
|
||||
EXPECT_THROW(slave.property("double4"), Property::undeclared);
|
||||
}
|
||||
|
||||
TEST_F(InitFromTest, function) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user