fw4spl
Writer.cpp
1 /* ***** BEGIN LICENSE BLOCK *****
2  * FW4SPL - Copyright (C) IRCAD, 2009-2015.
3  * Distributed under the terms of the GNU Lesser General Public License (LGPL) as
4  * published by the Free Software Foundation.
5  * ****** END LICENSE BLOCK ****** */
6 
7 #include "fwAtomsBoostIO/Writer.hpp"
8 
9 #include <fwAtoms/Base.hpp>
10 #include <fwAtoms/Blob.hpp>
11 #include <fwAtoms/Boolean.hpp>
12 #include <fwAtoms/Map.hpp>
13 #include <fwAtoms/Numeric.hpp>
14 #include <fwAtoms/Object.hpp>
15 #include <fwAtoms/Sequence.hpp>
16 #include <fwAtoms/String.hpp>
17 #include <fwMemory/BufferManager.hpp>
18 
19 #include <fwMemory/BufferManager.hpp>
20 #include <fwTools/UUID.hpp>
21 
22 #include <fwZip/IWriteArchive.hpp>
23 
24 #include <boost/filesystem/operations.hpp>
25 #include <boost/filesystem/path.hpp>
26 #include <boost/lexical_cast.hpp>
27 #include <boost/property_tree/json_parser.hpp>
28 #include <boost/property_tree/xml_parser.hpp>
29 
30 namespace fwAtomsBoostIO
31 {
32 
33 const std::string Writer::s_VERSION = "1";
34 const std::string Writer::s_ATOMS_VERSION_KEY = "atoms_version";
35 const std::string Writer::s_WRITER_VERSION_KEY = "writer_version";
36 
37 //-----------------------------------------------------------------------------
38 
40 {
41 
42  typedef std::map< ::fwAtoms::Base::sptr, ::boost::property_tree::ptree > PropTreeCacheType;
43 
44  PropTreeCacheType m_cache;
45  ::fwZip::IWriteArchive::sptr m_archive;
46  const std::string m_dirPrefix;
47 
48  AtomVisitor(const ::fwZip::IWriteArchive::sptr& archive, const std::string &dirPrefix) :
49  m_archive(archive),
50  m_dirPrefix(dirPrefix)
51  {
52  }
53 
54 //-----------------------------------------------------------------------------
55 
56  PropTreeCacheType::mapped_type hitCache(const PropTreeCacheType::key_type &atom) const
57  {
58  PropTreeCacheType::const_iterator iter = m_cache.find(atom);
59  if(iter != m_cache.end())
60  {
61  return iter->second;
62  }
63  return PropTreeCacheType::mapped_type();
64  }
65 
66 //-----------------------------------------------------------------------------
67 
68  void cache(const PropTreeCacheType::key_type &atom, const std::string &ptpath)
69  {
70  ::boost::property_tree::ptree ref;
71  ref.put("ref", ptpath );
72  m_cache.insert( PropTreeCacheType::value_type( atom, ref ) );
73  }
74 
75 //-----------------------------------------------------------------------------
76 
77  ::boost::property_tree::ptree visit(const ::fwAtoms::Boolean::sptr &atom, const std::string &ptpath)
78  {
79  ::boost::property_tree::ptree pt;
80  this->cache(atom, ptpath);
81  pt.put("boolean.value", atom->getValue() ? "true" : "false");
82  return pt;
83  }
84 
85 //-----------------------------------------------------------------------------
86 
87  ::boost::property_tree::ptree visit(const ::fwAtoms::Numeric::sptr &atom, const std::string &ptpath)
88  {
89  ::boost::property_tree::ptree pt;
90  this->cache(atom, ptpath);
91  pt.put("numeric.value", atom->getString());
92  return pt;
93  }
94 
95 //-----------------------------------------------------------------------------
96 
97  ::boost::property_tree::ptree visit(const ::fwAtoms::String::sptr &atom, const std::string &ptpath)
98  {
99  ::boost::property_tree::ptree pt;
100  this->cache(atom, ptpath);
101  pt.put("string.value", atom->getString());
102  return pt;
103  }
104 
105 //-----------------------------------------------------------------------------
106 
107  ::boost::property_tree::ptree visit(const ::fwAtoms::Map::sptr &atom, const std::string &ptpath)
108  {
109  ::boost::property_tree::ptree pt;
110  ::boost::property_tree::ptree map;
111  this->cache(atom, ptpath);
112  std::string path = ptpath + (ptpath.empty() ? "" : ".") + "map";
113  unsigned long long count = 0;
114  for(const ::fwAtoms::Map::MapType::value_type& elt : atom->getValue())
115  {
116  const std::string nodeName = "item_" + ::boost::lexical_cast< std::string >(count++);
117  ::boost::property_tree::ptree mapChild;
118  mapChild.put("key", elt.first);
119  mapChild.add_child("value", this->visit(elt.second, path + "." + nodeName + ".value"));
120 
121  map.add_child(nodeName, mapChild);
122  }
123  pt.add_child("map", map);
124  return pt;
125  }
126 
127 //-----------------------------------------------------------------------------
128 
129  ::boost::property_tree::ptree visit(const ::fwAtoms::Sequence::sptr &atom, const std::string &ptpath)
130  {
131  ::boost::property_tree::ptree pt;
132  ::boost::property_tree::ptree seq;
133  this->cache(atom, ptpath);
134  std::string path = ptpath + (ptpath.empty() ? "" : ".") + "sequence";
135 
136  unsigned long long count = 0;
137  for( const ::fwAtoms::Sequence::SequenceType::value_type& elt : atom->getValue())
138  {
139  const std::string nodeName = ::boost::lexical_cast< std::string >(count++);
140  seq.add_child(nodeName, this->visit(elt, path + "." + nodeName));
141  }
142  pt.add_child("sequence", seq);
143  return pt;
144  }
145 
146 //-----------------------------------------------------------------------------
147 
148  ::boost::property_tree::ptree visit(const ::fwAtoms::Object::sptr &atom, const std::string &ptpath)
149  {
150  ::boost::property_tree::ptree pt;
151  ::boost::property_tree::ptree object;
152  this->cache(atom, ptpath);
153  std::string path = ptpath + (ptpath.empty() ? "" : ".") + "object";
154 
155  const ::fwAtoms::Object::MetaInfosType& metaInfos = atom->getMetaInfos();
156  ::boost::property_tree::ptree metaInfosPt;
157  unsigned long long count = 0;
158  for(const ::fwAtoms::Object::MetaInfosType::value_type& info : metaInfos)
159  {
160  const std::string nodeName = "item_" + ::boost::lexical_cast< std::string >(count++);
161  ::boost::property_tree::ptree item;
162  item.put("key", info.first);
163  item.put("value", info.second);
164  metaInfosPt.push_back(::boost::property_tree::ptree::value_type(nodeName, item));
165  }
166  object.add_child("meta_infos", metaInfosPt);
167 
168  const ::fwAtoms::Object::AttributesType& attributes = atom->getAttributes();
169  ::boost::property_tree::ptree attributesPt;
170  for(const ::fwAtoms::Object::AttributesType::value_type& attr : attributes)
171  {
172  ::boost::property_tree::ptree childAttributes =
173  this->visit(attr.second, path + ".attributes." + attr.first);
174  attributesPt.add_child(attr.first, childAttributes);
175  }
176  object.add_child("attributes", attributesPt);
177 
178  pt.add_child("object", object);
179 
180  return pt;
181  }
182 
183 //-----------------------------------------------------------------------------
184 
185  ::boost::property_tree::ptree visit(const ::fwAtoms::Blob::sptr &atom, const std::string &ptpath)
186  {
187  ::boost::property_tree::ptree pt;
188  this->cache(atom, ptpath);
189  std::string path = ptpath + (ptpath.empty() ? "" : ".") + "blob";
190 
191  std::string bufType = "raw";
192  pt.put("blob.buffer_type", bufType);
193 
194  ::fwMemory::BufferObject::sptr buffObj = atom->getBufferObject();
195  if (!buffObj || buffObj->getSize() == 0)
196  {
197  pt.put("blob.buffer_size", 0);
198  }
199  else
200  {
201  ::boost::filesystem::path bufFile = m_dirPrefix;
202  size_t buffSize = buffObj->getSize();
203 
204  const ::fwMemory::BufferManager::StreamInfo streamInfo = buffObj->getStreamInfo();
205  const ::boost::filesystem::path dumpedFile = streamInfo.fsFile;
206  const ::fwMemory::FileFormatType& format = streamInfo.format;
207 
208  bufFile /= ::fwTools::UUID::generateUUID() + ".raw";
209 
210  if ( !dumpedFile.empty() && (format & ::fwMemory::RAW) )
211  {
212  m_archive->putFile(dumpedFile, bufFile);
213  }
214  else
215  {
216  SPTR(std::istream) is = streamInfo.stream;
217  SLM_ASSERT("no istream", is);
218 
219  SPTR(std::ostream) os = m_archive->createFile(bufFile);
220  *os << is->rdbuf();
221  }
222 
223  pt.put("blob.buffer_size", buffSize);
224  pt.put("blob.buffer", bufFile.generic_string());
225  }
226 
227  return pt;
228  }
229 
230 //-----------------------------------------------------------------------------
231 
232  ::boost::property_tree::ptree visit(const ::fwAtoms::Base::sptr &atom, std::string ptpath = "")
233  {
234  ::boost::property_tree::ptree pt;
235  ::boost::property_tree::ptree ref;
236 
237  if (!atom)
238  {
239  return pt;
240  }
241 
242  ref = this->hitCache(atom);
243  if( !ref.empty() )
244  {
245  return ref;
246  }
247 
248  switch(atom->type())
249  {
250  case ::fwAtoms::Base::BOOLEAN:
251  pt = this->visit(::fwAtoms::Boolean::dynamicCast(atom), ptpath);
252  break;
253  case ::fwAtoms::Base::NUMERIC:
254  pt = this->visit(::fwAtoms::Numeric::dynamicCast(atom), ptpath);
255  break;
256  case ::fwAtoms::Base::STRING:
257  pt = this->visit(::fwAtoms::String::dynamicCast(atom), ptpath);
258  break;
259  case ::fwAtoms::Base::OBJECT:
260  pt = this->visit(::fwAtoms::Object::dynamicCast(atom), ptpath);
261  break;
262  case ::fwAtoms::Base::SEQUENCE:
263  pt = this->visit(::fwAtoms::Sequence::dynamicCast(atom), ptpath);
264  break;
265  case ::fwAtoms::Base::MAP:
266  pt = this->visit(::fwAtoms::Map::dynamicCast(atom), ptpath);
267  break;
268  case ::fwAtoms::Base::BLOB:
269  pt = this->visit(::fwAtoms::Blob::dynamicCast(atom), ptpath);
270  break;
271  default:
272  FW_RAISE("Atome type '"<<atom->type()<<"' is not supported");
273  break;
274  }
275  return pt;
276  }
277 };
278 
279 //-----------------------------------------------------------------------------
280 
281 void Writer::write( const ::fwZip::IWriteArchive::sptr& archive,
282  const ::boost::filesystem::path& rootFilename,
283  FormatType format ) const
284 {
285  ::boost::property_tree::ptree root;
286  AtomVisitor visitor(archive, rootFilename.stem().string() + "-" + ((format==JSON) ? "json" : "xml"));
287 
288  root = visitor.visit(m_atom);
289 
290  ::boost::property_tree::ptree versions;
291  versions.put(s_ATOMS_VERSION_KEY, ::fwAtoms::Base::s_VERSION);
292  versions.put(s_WRITER_VERSION_KEY, Writer::s_VERSION);
293 
294  root.add_child("versions", versions);
295 
296  SPTR(std::ostream) os = archive->createFile(rootFilename);
297  switch(format)
298  {
299  case JSON:
300  ::boost::property_tree::json_parser::write_json(*os, root, false);
301  break;
302  case XML:
303  {
304  ::boost::property_tree::xml_writer_settings<std::string> settings(' ', 4);
305  ::boost::property_tree::xml_parser::write_xml(*os, root, settings);
306  break;
307  }
308  default:
309  FW_RAISE("Archive format '"<<format<<"' is not supported");
310  break;
311  }
312 }
313 
314 }
#define SPTR(_cls_)
The namespace fwAtomsBoostIO contains atom reader and writer.
static FWATOMSBOOSTIO_API const std::string s_ATOMS_VERSION_KEY
Defines key to retrieve fwAtoms version from file.
Definition: Writer.hpp:40
static FWATOMSBOOSTIO_API const std::string s_WRITER_VERSION_KEY
Defines key to retrieve writer version from file.
Definition: Writer.hpp:43
#define SLM_ASSERT(message, cond)
work like &#39;assert&#39; from &#39;cassert&#39;, with in addition a message logged by spylog (with FATAL loglevel) ...
Definition: spyLog.hpp:308
static FWATOMSBOOSTIO_API const std::string s_VERSION
Defines writer version.
Definition: Writer.hpp:37
static FWATOMS_API const std::string s_VERSION
Defines fwAtoms version.
static FWTOOLS_API UUIDType generateUUID()
Return a new extended UUID;.
Definition: UUID.cpp:114