create a metadata holding class
authorDiane Trout <diane@caltech.edu>
Fri, 30 Mar 2007 18:34:34 +0000 (18:34 +0000)
committerDiane Trout <diane@caltech.edu>
Fri, 30 Mar 2007 18:34:34 +0000 (18:34 +0000)
alg/annotations.cpp [new file with mode: 0644]
alg/annotations.hpp [new file with mode: 0644]
alg/test/CMakeLists.txt
alg/test/test_annotations.cpp [new file with mode: 0644]

diff --git a/alg/annotations.cpp b/alg/annotations.cpp
new file mode 100644 (file)
index 0000000..ff84ffe
--- /dev/null
@@ -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 (file)
index 0000000..203456b
--- /dev/null
@@ -0,0 +1,58 @@
+#ifndef ANNOTATIONS_HPP_
+#define ANNOTATIONS_HPP_
+
+#include <string>
+#include <map>
+
+#include <boost/shared_ptr.hpp>
+
+#include "mussa_exceptions.hpp"
+
+class Annotations;
+typedef boost::shared_ptr<Annotations> 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<std::string, std::string> 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<std::string> keys() const;
+  size_type size() const { return metadata.size(); }
+  //@}
+protected:
+  metadata_map metadata;
+};
+#endif /*ANNOTATIONS_HPP_*/
index c3f8d09b5d7c63280b673f9ba30603ccf5e6aa6e..b766624de61642759f42f57905b474034b7a38e3 100644 (file)
@@ -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 (file)
index 0000000..8bb0bea
--- /dev/null
@@ -0,0 +1,64 @@
+#define BOOST_AUTO_TEST_MAIN
+#include <boost/test/auto_unit_test.hpp>
+
+#include <boost/shared_ptr.hpp>
+#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<Annotations> asp(new Annotations);
+  BOOST_CHECK_EQUAL(asp->name(), "");
+  
+  boost::shared_ptr<Annotations> 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<Annotations> 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<Annotations> 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