From 2dea10e86e45dfef6deb896be3fb14343e1f4006 Mon Sep 17 00:00:00 2001 From: Diane Trout Date: Fri, 30 Mar 2007 18:34:34 +0000 Subject: [PATCH] create a metadata holding class --- alg/annotations.cpp | 60 ++++++++++++++++++++++++++++++++ alg/annotations.hpp | 58 +++++++++++++++++++++++++++++++ alg/test/CMakeLists.txt | 1 + alg/test/test_annotations.cpp | 64 +++++++++++++++++++++++++++++++++++ 4 files changed, 183 insertions(+) create mode 100644 alg/annotations.cpp create mode 100644 alg/annotations.hpp create mode 100644 alg/test/test_annotations.cpp diff --git a/alg/annotations.cpp b/alg/annotations.cpp new file mode 100644 index 0000000..ff84ffe --- /dev/null +++ b/alg/annotations.cpp @@ -0,0 +1,60 @@ +#include "annotations.hpp" + +const std::string Annotations::name_str("name"); + +Annotations::Annotations() +{ + metadata[name_str] = ""; +} + +Annotations::Annotations(const std::string &n) +{ + metadata[name_str] = n; +} + +Annotations::Annotations(const Annotations& a) : + metadata(a.metadata) +{ +} + +Annotations::Annotations(const AnnotationsRef a) : + metadata(a->metadata) +{ +} + +AnnotationsRef Annotations::copy() const +{ + AnnotationsRef a(new Annotations(*this)); + return a; +} + +void Annotations::erase(const std::string& key) +{ + if (key == name_str) { + // we must always have a name + metadata[key] = ""; + } else { + metadata.erase(key); + } +} + +void Annotations::set(const std::string& key, const std::string &value ) +{ + metadata[key] = value; +} + +std::string Annotations::get(const std::string& key) const +{ + metadata_map::const_iterator map_i(metadata.find(key)); + if (map_i == metadata.end()) { + throw annotations_key_error(key + " was not found"); + } else { + return map_i->second; + } +} + +bool Annotations::has_key(const std::string& key) const +{ + metadata_map::const_iterator map_i(metadata.find(key)); + return map_i != metadata.end(); +} \ No newline at end of file diff --git a/alg/annotations.hpp b/alg/annotations.hpp new file mode 100644 index 0000000..203456b --- /dev/null +++ b/alg/annotations.hpp @@ -0,0 +1,58 @@ +#ifndef ANNOTATIONS_HPP_ +#define ANNOTATIONS_HPP_ + +#include +#include + +#include + +#include "mussa_exceptions.hpp" + +class Annotations; +typedef boost::shared_ptr AnnotationsRef; + +/** + * \brief Annotations provides a simple "dictionary" of name value pairs + * + * The intent is that this is to be used as a mix-in class to add + * a uniform way of storing annotation metadata. + */ +class Annotations { +protected: + static const std::string name_str; + +public: + typedef std::map metadata_map; + typedef metadata_map::size_type size_type; + + Annotations(); + Annotations(const std::string& n); + Annotations(const Annotations&); + Annotations(const AnnotationsRef); + + //! make a shared pointer copy of our object + AnnotationsRef copy() const; + + //! provide a special case for accessing a name + std::string name() const { return metadata.find(name_str)->second; } + //! special case for setting name + void setName(const std::string& n) { metadata[name_str] = n; } + + //! Generic metadata handling + //@{ + //! remove some key from our "dictionary" + void erase(const std::string& key); + //! set a metadata element + void set(const std::string& key, const std::string &value ); + //! look for a key, \throws annotation_key_error if it doesn't find it + std::string get(const std::string& key) const; + //! check for a key + bool has_key(const std::string& key) const; + //! return all the keys of our metadata map + //std::list keys() const; + size_type size() const { return metadata.size(); } + //@} +protected: + metadata_map metadata; +}; +#endif /*ANNOTATIONS_HPP_*/ diff --git a/alg/test/CMakeLists.txt b/alg/test/CMakeLists.txt index c3f8d09..b766624 100644 --- a/alg/test/CMakeLists.txt +++ b/alg/test/CMakeLists.txt @@ -43,6 +43,7 @@ ENDMACRO(MAKE_ALG_UNITTEST) #add all our main tests MAKE_ALG_UNITTEST( test_alphabet ) +MAKE_ALG_UNITTEST( test_annotations ) MAKE_ALG_UNITTEST( test_annotation_color ) MAKE_ALG_UNITTEST( test_color ) MAKE_ALG_UNITTEST( test_conserved_path ) diff --git a/alg/test/test_annotations.cpp b/alg/test/test_annotations.cpp new file mode 100644 index 0000000..8bb0bea --- /dev/null +++ b/alg/test/test_annotations.cpp @@ -0,0 +1,64 @@ +#define BOOST_AUTO_TEST_MAIN +#include + +#include +#include "annotations.hpp" +#include "mussa_exceptions.hpp" + +BOOST_AUTO_TEST_CASE( annotations_constructors ) +{ + Annotations a; + BOOST_CHECK_EQUAL(a.name(), ""); + + Annotations b("bee"); + BOOST_CHECK_EQUAL(b.name(), "bee"); + + boost::shared_ptr asp(new Annotations); + BOOST_CHECK_EQUAL(asp->name(), ""); + + boost::shared_ptr bsp(new Annotations("bee pointer")); + BOOST_CHECK_EQUAL(bsp->name(), "bee pointer"); +} + +BOOST_AUTO_TEST_CASE( annotations_copy_constructor ) +{ + AnnotationsRef a(new Annotations("a")); + AnnotationsRef b(a); + AnnotationsRef c(new Annotations(a)); + + // b is a copy of a's pointer and thus changes + // to b update a + b->setName("bee"); + BOOST_CHECK_EQUAL(a->name(), "bee"); + BOOST_CHECK_EQUAL(b->name(), "bee"); + + // c is a copy of a, and not a pointer to a + // so updates of a, b wont affect c and vice versa + BOOST_CHECK_EQUAL(c->name(), "a"); + c->setName("cee"); + BOOST_CHECK_EQUAL(c->name(), "cee"); + + BOOST_CHECK_EQUAL(a->name(), "bee"); + BOOST_CHECK_EQUAL(b->name(), "bee"); + +} + +BOOST_AUTO_TEST_CASE( annotations_get_metadata ) +{ + boost::shared_ptr asp(new Annotations("asp")); + asp->set("header", "> amsp"); + + BOOST_CHECK_EQUAL( asp->size(), 2 ); + BOOST_CHECK_EQUAL( asp->get("header"), "> amsp" ); + BOOST_CHECK_THROW( asp->get("not there"), annotations_key_error ); +} + +BOOST_AUTO_TEST_CASE( annotations_has_key ) +{ + boost::shared_ptr asp(new Annotations("asp")); + asp->set("header", "> amsp"); + + BOOST_CHECK_EQUAL(asp->has_key("header"), true); + BOOST_CHECK_EQUAL(asp->has_key("name"), true); + BOOST_CHECK_EQUAL(asp->has_key("secret"), false); +} \ No newline at end of file -- 2.30.2