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:
|
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;
|
typedef int SourceId;
|
||||||
/// function callback used to initialize property value from another PropertyMap
|
/// function callback used to initialize property value from another PropertyMap
|
||||||
typedef std::function<boost::any(const PropertyMap& other)> InitializerFunction;
|
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.
|
/** PropertyMap is map of (name, Property) pairs.
|
||||||
*
|
*
|
||||||
* Conveniency methods are provided to setup property initialization for several
|
* 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>);
|
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);
|
Property& property(const std::string &name);
|
||||||
const Property& property(const std::string &name) const {
|
const Property& property(const std::string &name) const {
|
||||||
return const_cast<PropertyMap*>(this)->property(name);
|
return const_cast<PropertyMap*>(this)->property(name);
|
||||||
@ -190,15 +225,15 @@ public:
|
|||||||
/// temporarily set the value of a property
|
/// temporarily set the value of a property
|
||||||
void setCurrent(const std::string& name, const boost::any& value);
|
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;
|
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>
|
template<typename T>
|
||||||
const T& get(const std::string& name) const {
|
const T& get(const std::string& name) const {
|
||||||
const boost::any& value = get(name);
|
const boost::any& value = get(name);
|
||||||
if (value.empty())
|
if (value.empty())
|
||||||
throw std::runtime_error(std::string("undefined property: " + name));
|
throw Property::undefined(name);
|
||||||
return boost::any_cast<const T&>(value);
|
return boost::any_cast<const T&>(value);
|
||||||
}
|
}
|
||||||
/// get typed value of property, using fallback if undefined. Throws bad_any_cast on type mismatch.
|
/// 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_);
|
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) {
|
void Property::setValue(const boost::any &value) {
|
||||||
setCurrentValue(value);
|
setCurrentValue(value);
|
||||||
default_ = value_;
|
default_ = value_;
|
||||||
@ -72,8 +62,9 @@ void Property::setValue(const boost::any &value) {
|
|||||||
|
|
||||||
void Property::setCurrentValue(const boost::any &value)
|
void Property::setCurrentValue(const boost::any &value)
|
||||||
{
|
{
|
||||||
if (!value.empty())
|
if (!value.empty() && std::type_index(value.type()) != type_index_)
|
||||||
typeCheck(value, type_index_);
|
throw Property::type_error(value.type().name(), type_index_.name());
|
||||||
|
|
||||||
value_ = value;
|
value_ = value;
|
||||||
if (signaller_)
|
if (signaller_)
|
||||||
signaller_(this);
|
signaller_(this);
|
||||||
@ -92,7 +83,7 @@ std::string Property::serialize() const {
|
|||||||
Property& Property::configureInitFrom(SourceId source, const Property::InitializerFunction &f)
|
Property& Property::configureInitFrom(SourceId source, const Property::InitializerFunction &f)
|
||||||
{
|
{
|
||||||
if (source != source_id_ && initializer_)
|
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;
|
source_id_ = source;
|
||||||
initializer_ = f;
|
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)));
|
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_)
|
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;
|
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)
|
Property& PropertyMap::property(const std::string &name)
|
||||||
{
|
{
|
||||||
auto it = props_.find(name);
|
auto it = props_.find(name);
|
||||||
if (it == props_.end())
|
if (it == props_.end())
|
||||||
throw std::runtime_error("Undeclared property '" + name + "'");
|
throw Property::undeclared(name);
|
||||||
return it->second;
|
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);
|
auto range = props_.equal_range(name);
|
||||||
if (range.first == range.second) { // name is not yet declared
|
if (range.first == range.second) { // name is not yet declared
|
||||||
if (value.empty())
|
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(),
|
auto it = props_.insert(range.first, std::make_pair(name, Property(value.type(), "", boost::any(),
|
||||||
Property::SerializeFunction())));
|
Property::SerializeFunction())));
|
||||||
it->second.setValue(value);
|
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 task_constructor
|
||||||
} // namespace moveit
|
} // namespace moveit
|
||||||
|
|||||||
@ -13,9 +13,9 @@ TEST(Property, standard) {
|
|||||||
|
|
||||||
EXPECT_EQ(props.get<double>("double1"), 1.0);
|
EXPECT_EQ(props.get<double>("double1"), 1.0);
|
||||||
EXPECT_EQ(props.get<double>("double2"), 2.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_FALSE(props.property("double4").defined());
|
||||||
EXPECT_EQ(props.get<double>("double4", 0.0), 0.0);
|
EXPECT_EQ(props.get<double>("double4", 0.0), 0.0);
|
||||||
|
|
||||||
@ -41,10 +41,10 @@ TEST(Property, redeclare) {
|
|||||||
|
|
||||||
// avoid second declaration with different type
|
// avoid second declaration with different type
|
||||||
props.declare<double>("double1");
|
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?
|
// 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);
|
props.set("double1", 3.14);
|
||||||
EXPECT_EQ(props.get<double>("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>("double1"), 1.0);
|
||||||
EXPECT_EQ(slave.get<double>("double2"), 2.0);
|
EXPECT_EQ(slave.get<double>("double2"), 2.0);
|
||||||
EXPECT_FALSE(slave.property("double3").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, limited) {
|
TEST_F(InitFromTest, limited) {
|
||||||
@ -117,7 +117,7 @@ TEST_F(InitFromTest, limited) {
|
|||||||
EXPECT_EQ(slave.get<double>("double1"), 1.0);
|
EXPECT_EQ(slave.get<double>("double1"), 1.0);
|
||||||
EXPECT_FALSE(slave.property("double2").defined());
|
EXPECT_FALSE(slave.property("double2").defined());
|
||||||
EXPECT_FALSE(slave.property("double3").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) {
|
TEST_F(InitFromTest, sourceId) {
|
||||||
@ -126,7 +126,7 @@ TEST_F(InitFromTest, sourceId) {
|
|||||||
EXPECT_FALSE(slave.property("double1").defined());
|
EXPECT_FALSE(slave.property("double1").defined());
|
||||||
EXPECT_FALSE(slave.property("double2").defined());
|
EXPECT_FALSE(slave.property("double2").defined());
|
||||||
EXPECT_FALSE(slave.property("double3").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) {
|
TEST_F(InitFromTest, multipleSourceIds) {
|
||||||
@ -141,7 +141,7 @@ TEST_F(InitFromTest, otherName) {
|
|||||||
EXPECT_EQ(slave.get<double>("double1"), 2.0);
|
EXPECT_EQ(slave.get<double>("double1"), 2.0);
|
||||||
EXPECT_FALSE(slave.property("double2").defined());
|
EXPECT_FALSE(slave.property("double2").defined());
|
||||||
EXPECT_FALSE(slave.property("double3").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) {
|
TEST_F(InitFromTest, function) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user