owlcpp  v0.3.3~
C++ library for working with OWL ontologies
 All Classes Namespaces Files Functions Macros Pages
map_doc.hpp
Go to the documentation of this file.
1 
6 #ifndef MAP_DOC_HPP_
7 #define MAP_DOC_HPP_
8 #include "boost/assert.hpp"
9 #include "owlcpp/config.hpp"
10 #include "boost/multi_index_container.hpp"
11 #include "boost/multi_index/hashed_index.hpp"
12 #include "boost/multi_index/mem_fun.hpp"
13 #include "boost/multi_index/member.hpp"
14 #include "boost/range.hpp"
15 #include "boost/foreach.hpp"
16 
17 
18 #include "owlcpp/doc_id.hpp"
19 #include "owlcpp/detail/id_tracker.hpp"
20 #include "owlcpp/rdf/doc_meta.hpp"
21 #include "owlcpp/detail/member_iterator.hpp"
23 
24 
25 namespace owlcpp{
26 
29 class Map_doc {
30  struct Doc_meta_wrap {
31  Doc_meta_wrap(
32  const Node_id ontology_iri,
33  const Node_id version_iri,
34  std::string const& path,
35  const Doc_id doc
36  )
37  : dm_(ontology_iri, version_iri, path), id_(doc)
38  {}
39 
40  Node_id ontology_iri() const {return dm_.ontology_iri;}
41  Node_id version_iri() const {return dm_.version_iri;}
42  std::string const& path() const {return dm_.path;}
43  Doc_meta dm_;
44  Doc_id id_;
45  };
46 
47  typedef boost::multi_index_container<
48  Doc_meta_wrap,
49  boost::multi_index::indexed_by<
50  boost::multi_index::hashed_unique<
51  boost::multi_index::tag<struct id_tag>,
52  boost::multi_index::member<
53  Doc_meta_wrap, Doc_id, &Doc_meta_wrap::id_
54  >
55  >,
56  boost::multi_index::hashed_non_unique<
57  boost::multi_index::tag<struct iri_tag>,
58  boost::multi_index::const_mem_fun<
59  Doc_meta_wrap, Node_id, &Doc_meta_wrap::ontology_iri
60  >
61  >,
62  boost::multi_index::hashed_non_unique<
63  boost::multi_index::tag<struct version_tag>,
64  boost::multi_index::const_mem_fun<
65  Doc_meta_wrap, Node_id, &Doc_meta_wrap::version_iri
66  >
67  >,
68  boost::multi_index::hashed_non_unique<
69  boost::multi_index::tag<struct path_tag>,
70  boost::multi_index::const_mem_fun<
71  Doc_meta_wrap, std::string const&, &Doc_meta_wrap::path
72  >
73  >
74  >
75  > map_t;
76 
77  typedef map_t::index<id_tag>::type id_index_t;
78  typedef map_t::index<path_tag>::type path_index_t;
79  typedef map_t::index<iri_tag>::type iri_index_t;
80  typedef map_t::index<version_tag>::type version_index_t;
81 
82 public:
83  typedef Member_iterator<
84  map_t::const_iterator,
85  const Doc_id,
86  &Doc_meta_wrap::id_
87  > const_iterator;
88  typedef const_iterator iterator;
89 
90  typedef Member_iterator<
91  path_index_t::const_iterator,
92  const Doc_id,
93  &Doc_meta_wrap::id_
94  > path_iterator;
95  typedef boost::iterator_range<path_iterator> path_range;
96 
97  typedef Member_iterator<
98  iri_index_t::const_iterator,
99  const Doc_id,
100  &Doc_meta_wrap::id_
101  > iri_iterator;
102  typedef boost::iterator_range<iri_iterator> iri_range;
103 
104  typedef Member_iterator<
105  version_index_t::const_iterator,
106  const Doc_id,
107  &Doc_meta_wrap::id_
108  > version_iterator;
109  typedef boost::iterator_range<version_iterator> version_range;
110 
111  struct Err : public base_exception {};
112 
113  std::size_t size() const {return m_.size();}
114  const_iterator begin() const {return m_.begin();}
115  const_iterator end() const {return m_.end();}
116 
117  Doc_meta const& operator[](const Doc_id did) const {
118  id_index_t const& index = m_.get<id_tag>();
119  const id_index_t::const_iterator iter = index.find(did);
120  BOOST_ASSERT( iter != index.end() );
121  return iter->dm_;
122  }
123 
124  Doc_meta const& at(const Doc_id did) const {
125  id_index_t const& index = m_.get<id_tag>();
126  const id_index_t::const_iterator iter = index.find(did);
127  if( iter == index.end() ) BOOST_THROW_EXCEPTION(
128  Err()
129  << Err::msg_t("invalid document ID")
130  << Err::int1_t(did())
131  );
132  return iter->dm_;
133  }
134 
135  Doc_meta const* find(const Doc_id did) const {
136  id_index_t const& index = m_.get<id_tag>();
137  const id_index_t::const_iterator iter = index.find(did);
138  if( iter == index.end() ) return 0;
139  return &iter->dm_;
140  }
141 
146  iri_range find_iri(const Node_id iri_id) const {
147  return m_.get<iri_tag>().equal_range(iri_id);
148  }
149 
154  version_range find_version(const Node_id version_id) const {
155  return m_.get<version_tag>().equal_range(version_id);
156  }
157 
158  path_range find_path(std::string const& path) const {
159  return m_.get<path_tag>().equal_range(path);
160  }
161 
184  std::pair<Doc_id,bool> insert(
185  const Node_id iri,
186  std::string const& path = "",
187  const Node_id vers = terms::empty_::id()
188  ) {
189  if( iri == terms::empty_::id() ) BOOST_THROW_EXCEPTION(
190  Err()
191  << Err::msg_t("empty ontologyIRI is not allowed")
192  << Err::str1_t(path)
193  );
194  if( iri == vers ) BOOST_THROW_EXCEPTION(
195  Err()
196  << Err::msg_t("ontologyIRI and versionIRI are same")
197  << Err::str1_t(path)
198  );
199 
200  Doc_id const* did = check_existing(iri, vers, path);
201  if( did ) return std::make_pair(*did, false);
202  const Doc_id id = idt_.get();
203  m_.insert(Doc_meta_wrap(iri, vers, path, id));
204  return std::make_pair(id, true);
205  }
206 
207  void clear() {
208  m_.clear();
209  idt_ = detail::Id_tracker<Doc_id>();
210  }
211 
212 private:
213  map_t m_;
214  detail::Id_tracker<Doc_id> idt_;
215 
216  Doc_id const* check_existing(
217  const Node_id iri,
218  const Node_id vers,
219  std::string const& path
220  ) const {
221  BOOST_ASSERT( ! is_empty(iri) );
222  Doc_id const* idp = 0;
223 
224  //check version
225  if( ! is_empty(vers) ) {
226  BOOST_FOREACH(
227  Doc_meta_wrap const& dmw,
228  m_.get<version_tag>().equal_range(vers)
229  ) {
230  BOOST_ASSERT( ! is_empty(dmw.ontology_iri()) );
231  if( dmw.ontology_iri() != iri ) BOOST_THROW_EXCEPTION(
232  Err()
233  << Err::msg_t("document with same versionIRI and "
234  "different ontologyIRI exists")
235  << Err::int1_t(dmw.id_())
236  );
237  if( path == dmw.path() ) idp = &dmw.id_;
238  }
239  }
240 
241  //check path
242  if( ! path.empty() ) {
243  BOOST_FOREACH(
244  Doc_meta_wrap const& dmw,
245  m_.get<path_tag>().equal_range(path)
246  ) {
247  if( dmw.ontology_iri() != iri || dmw.version_iri() != vers )
248  BOOST_THROW_EXCEPTION(
249  Err()
250  << Err::msg_t("different versionIRI or ontologyIRI is "
251  "recorded for same document")
252  << Err::str1_t(path)
253  << Err::int1_t(dmw.id_())
254  );
255  idp = &dmw.id_;
256  }
257  }
258 
259  if( is_empty(vers) && path.empty() ) {
260  if( const iri_range r = find_iri(iri) ) {
261  idp = &(*r.begin());
262  BOOST_ASSERT( distance(r) == 1 );
263  }
264  }
265  return idp;
266  }
267 
268 };
269 
270 }//namespace owlcpp
271 #endif /* MAP_DOC_HPP_ */