fw4spl
AtomToDataMappingVisitor.cpp
1 /* ***** BEGIN LICENSE BLOCK *****
2  * FW4SPL - Copyright (C) IRCAD, 2009-2018.
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 "fwAtomConversion/AtomToDataMappingVisitor.hpp"
8 
9 #include "fwAtomConversion/camp_ext/ValueMapper.hpp"
10 #include "fwAtomConversion/convert.hpp"
11 #include "fwAtomConversion/DataVisitor.hpp"
12 #include "fwAtomConversion/exception/ConversionNotManaged.hpp"
13 #include "fwAtomConversion/mapper/Base.hpp"
14 
15 #include <fwAtoms/Blob.hpp>
16 #include <fwAtoms/Boolean.hpp>
17 #include <fwAtoms/Map.hpp>
18 #include <fwAtoms/Numeric.hpp>
19 #include <fwAtoms/Numeric.hxx>
20 #include <fwAtoms/Sequence.hpp>
21 
22 #include <fwCamp/factory/new.hpp>
23 
24 #include <fwData/Object.hpp>
25 
26 #include <fwMemory/BufferObject.hpp>
27 
28 namespace fwAtomConversion
29 {
30 
31 //-----------------------------------------------------------------------------
32 
33 class NumericSimplePropertyVisitor : public boost::static_visitor<void>
34 {
35 public:
36 
37  ::fwAtoms::Numeric::sptr m_typedAtom;
38  ::camp::UserObject& m_campDataObj;
39  const camp::SimpleProperty& m_property;
40 
41  NumericSimplePropertyVisitor( const ::fwAtoms::Numeric::sptr& typedAtom,
42  ::camp::UserObject& campDataObj,
43  const camp::SimpleProperty& property ) :
44  m_typedAtom(typedAtom),
45  m_campDataObj(campDataObj),
46  m_property(property)
47  {
48  }
49 
50  //------------------------------------------------------------------------------
51 
52  void operator()( ::boost::blank& ) const
53  {
54  m_property.set( m_campDataObj, m_typedAtom->getString() );
55  }
56 
57  //------------------------------------------------------------------------------
58 
59  void operator()( const ::boost::blank& ) const
60  {
61  m_property.set( m_campDataObj, m_typedAtom->getString() );
62  }
63 
64  //------------------------------------------------------------------------------
65 
66  template <typename U>
67  void operator()( U& value ) const
68  {
69  m_property.set( m_campDataObj, value );
70  }
71 };
72 
73 //-----------------------------------------------------------------------------
74 
75 class NumericArrayPropertyVisitor : public boost::static_visitor<void>
76 {
77 public:
78 
79  ::fwAtoms::Numeric::sptr m_typedAtom;
80  ::camp::UserObject& m_campDataObj;
81  const camp::ArrayProperty& m_property;
82  unsigned int m_index;
83 
84  NumericArrayPropertyVisitor( const ::fwAtoms::Numeric::sptr& typedAtom,
85  ::camp::UserObject& campDataObj,
86  const camp::ArrayProperty& property,
87  unsigned int index ) :
88  m_typedAtom(typedAtom),
89  m_campDataObj(campDataObj),
90  m_property(property),
91  m_index(index)
92  {
93  }
94 
95  //------------------------------------------------------------------------------
96 
97  void operator()( ::boost::blank& ) const
98  {
99  if( m_property.dynamic() )
100  {
101  m_property.insert( m_campDataObj, m_index, m_typedAtom->getString() );
102  }
103  else
104  {
105  m_property.set( m_campDataObj, m_index, m_typedAtom->getString() );
106  }
107  }
108 
109  //------------------------------------------------------------------------------
110 
111  void operator()( const ::boost::blank& ) const
112  {
113  if( m_property.dynamic() )
114  {
115  m_property.insert( m_campDataObj, m_index, m_typedAtom->getString() );
116  }
117  else
118  {
119  m_property.set( m_campDataObj, m_index, m_typedAtom->getString() );
120  }
121  }
122 
123  //------------------------------------------------------------------------------
124 
125  template <typename U>
126  void operator()( U& value ) const
127  {
128  if( m_property.dynamic() )
129  {
130  m_property.insert( m_campDataObj, m_index, value );
131  }
132  else
133  {
134  m_property.set( m_campDataObj, m_index, value );
135  }
136  }
137 };
138 
139 //-----------------------------------------------------------------------------
140 class NumericMapPropertyVisitor : public boost::static_visitor<void>
141 {
142 public:
143 
144  ::fwAtoms::Numeric::sptr m_typedAtom;
145  ::camp::UserObject& m_campDataObj;
146  const camp::MapProperty& m_property;
147  std::string m_key;
148 
149  NumericMapPropertyVisitor( const ::fwAtoms::Numeric::sptr& typedAtom,
150  ::camp::UserObject& campDataObj,
151  const camp::MapProperty& property,
152  const std::string& key ) :
153  m_typedAtom(typedAtom),
154  m_campDataObj(campDataObj),
155  m_property(property),
156  m_key(key)
157  {
158  }
159 
160  //------------------------------------------------------------------------------
161 
162  void operator()( ::boost::blank& ) const
163  {
164  m_property.set( m_campDataObj, m_key, m_typedAtom->getString() );
165  }
166 
167  //------------------------------------------------------------------------------
168 
169  void operator()( const ::boost::blank& ) const
170  {
171  m_property.set( m_campDataObj, m_key, m_typedAtom->getString() );
172  }
173 
174  //------------------------------------------------------------------------------
175 
176  template <typename U>
177  void operator()( U& value ) const
178  {
179  m_property.set( m_campDataObj, m_key, value );
180  }
181 };
182 
183 //-----------------------------------------------------------------------------
184 
186  ::fwData::Object::sptr dataObj,
187  ::fwAtoms::Object::sptr atomObj,
188  AtomVisitor::DataCacheType& cache,
189  const AtomVisitor::IReadPolicy& uuidPolicy) :
190  m_dataObj(dataObj),
191  m_campDataObj( m_dataObj.get() ),
192  m_atomObj(atomObj),
193  m_cache(cache),
194  m_uuidPolicy(uuidPolicy)
195 {
196 }
197 
199 {
200 }
201 
202 //------------------------------------------------------------------------------
203 
204 void AtomToDataMappingVisitor::visit(const camp::SimpleProperty& property)
205 {
206  const std::string& name( property.name() );
207  ::fwAtoms::Base::sptr atom = m_atomObj->getAttribute( name );
208 
209  std::stringstream msg;
210  msg << "Atom attribute is not well formed. Attribute '" << name << "' missing for data conversion";
211  FW_RAISE_EXCEPTION_IF( exception::ConversionNotManaged( msg.str() ), !atom );
212 
213  switch( atom->type() )
214  {
215  case ::fwAtoms::Base::NUMERIC:
216  {
217  ::fwAtoms::Numeric::sptr typedAtom = ::fwAtoms::Numeric::dynamicCast( atom );
218  ::boost::apply_visitor( NumericSimplePropertyVisitor(typedAtom, m_campDataObj, property),
219  typedAtom->getVariant() );
220  break;
221  }
222  default:
223  {
224  property.set( m_campDataObj, atom->getString() );
225  break;
226  }
227  }
228 
229 }
230 
231 //------------------------------------------------------------------------------
232 
233 void AtomToDataMappingVisitor::visit(const camp::EnumProperty& property)
234 {
235  const std::string& name( property.name() );
236  ::fwAtoms::Base::sptr atom = m_atomObj->getAttribute( name );
237 
238  std::stringstream msg;
239  msg << "Atom attribute is not well formed. Attribute '" << name << "' missing for data conversion";
240  FW_RAISE_EXCEPTION_IF( exception::ConversionNotManaged( msg.str() ), !atom );
241 
242  property.set( m_campDataObj, atom->getString() );
243 }
244 
245 //------------------------------------------------------------------------------
246 
247 void AtomToDataMappingVisitor::visit(const camp::UserProperty& property)
248 {
249  const std::string& name( property.name() );
250  ::fwAtoms::Base::sptr atom = m_atomObj->getAttribute( name );
251  if ( atom ) // attribute not exist if was a null object sptr
252  {
253  switch( atom->type() )
254  {
255  case ::fwAtoms::Base::BLOB:
256  {
257  ::fwAtoms::Blob::sptr blobAtom = ::fwAtoms::Blob::dynamicCast(atom);
258  ::fwMemory::BufferObject::sptr buffer;
259  buffer = ::camp_ext::ValueMapper< ::fwAtoms::Blob::sptr >::to(blobAtom);
260  FW_RAISE_EXCEPTION_IF( exception::ConversionNotManaged(
261  "A blob cannot contain a null buffer pointer"),
262  !buffer );
263  property.set( m_campDataObj, ::camp::UserObject(buffer) );
264  break;
265  }
266  case ::fwAtoms::Base::OBJECT:
267  {
268  ::fwAtoms::Object::sptr objectAtom = ::fwAtoms::Object::dynamicCast(atom);
269  ::fwData::Object::sptr objectData = ::fwAtomConversion::convert( objectAtom, m_cache, m_uuidPolicy );
270  property.set( m_campDataObj, objectData );
271  break;
272  }
273  default:
274  {
275  std::stringstream msg;
276  msg << "Attribute of type '";
277  switch( atom->type() )
278  {
279  case ::fwAtoms::Base::BOOLEAN:
280  msg << "BOOLEAN";
281  break;
282  case ::fwAtoms::Base::STRING:
283  msg << "STRING";
284  break;
285  case ::fwAtoms::Base::NUMERIC:
286  msg << "NUMERIC";
287  break;
288  case ::fwAtoms::Base::MAP:
289  msg << "MAP";
290  break;
291  case ::fwAtoms::Base::SEQUENCE:
292  msg << "SEQUENCE";
293  break;
294  default:
295  break;
296  }
297  msg <<"', are not supported in the data conversion process.";
298  FW_RAISE_EXCEPTION( exception::ConversionNotManaged(msg.str()) );
299  break;
300  }
301  }
302  }
303 }
304 
305 //------------------------------------------------------------------------------
306 
307 void AtomToDataMappingVisitor::visit(const camp::ArrayProperty& property)
308 {
309  const std::string& name( property.name() );
310  ::fwAtoms::Base::sptr atom = m_atomObj->getAttribute( name );
311 
312  std::stringstream msg;
313  msg << "Atom attribute is not well formed. Attribute '" << name << "' missing for data conversion";
314  FW_RAISE_EXCEPTION_IF( exception::ConversionNotManaged( msg.str() ), !atom );
315 
316  ::fwAtoms::Sequence::sptr seqAtom = ::fwAtoms::Sequence::dynamicCast(atom);
317  unsigned int index = 0;
318  for( ::fwAtoms::Base::sptr elemAtom : seqAtom->getValue() )
319  {
320  if (!elemAtom)
321  {
322  FW_RAISE_EXCEPTION_IF( exception::ConversionNotManaged( "Not supported null element in Atom sequence." ),
323  property.elementType() != ::camp::userType );
324 
325  ::fwData::Object::sptr objectData;
326  if( property.dynamic() )
327  {
328  property.insert( m_campDataObj, index, objectData );
329  }
330  else
331  {
332  property.set( m_campDataObj, index, objectData );
333  }
334  }
335  else
336  {
337  switch( elemAtom->type() )
338  {
339  case ::fwAtoms::Base::BOOLEAN:
340  case ::fwAtoms::Base::STRING:
341  {
342  std::string value = elemAtom->getString();
343 
344  if( property.dynamic() )
345  {
346  property.insert( m_campDataObj, index, value );
347  }
348  else
349  {
350  property.set( m_campDataObj, index, value );
351  }
352  break;
353  }
354  case ::fwAtoms::Base::NUMERIC:
355  {
356  ::fwAtoms::Numeric::sptr typedAtom = ::fwAtoms::Numeric::dynamicCast( elemAtom );
357  ::boost::apply_visitor( NumericArrayPropertyVisitor(typedAtom, m_campDataObj, property, index),
358  typedAtom->getVariant() );
359  break;
360  }
361 
362  case ::fwAtoms::Base::OBJECT:
363  {
364  ::fwAtoms::Object::sptr objectAtom = ::fwAtoms::Object::dynamicCast(elemAtom);
365  ::fwData::Object::sptr objectData =
366  ::fwAtomConversion::convert( objectAtom, m_cache, m_uuidPolicy);
367 
368  if( property.dynamic() )
369  {
370  property.insert( m_campDataObj, index, objectData );
371  }
372  else
373  {
374  property.set( m_campDataObj, index, objectData );
375  }
376  break;
377  }
378  default:
379  {
380  std::stringstream msg;
381  msg << "fwAtoms::Sequence elements of type '";
382  switch( elemAtom->type() )
383  {
384  case ::fwAtoms::Base::BLOB:
385  msg << "BLOB";
386  break;
387  case ::fwAtoms::Base::MAP:
388  msg << "MAP";
389  break;
390  case ::fwAtoms::Base::SEQUENCE:
391  msg << "SEQUENCE";
392  break;
393  default:
394  break;
395  }
396  msg <<"', are not supported in the data conversion process.";
397  FW_RAISE_EXCEPTION( exception::ConversionNotManaged(msg.str()) );
398  break;
399  }
400  }
401  }
402  ++index;
403  }
404 }
405 
406 //------------------------------------------------------------------------------
407 
409 {
410  const std::string& name( property.name() );
411  ::fwAtoms::Base::sptr atom = m_atomObj->getAttribute( name );
412 
413  std::stringstream msg;
414  msg << "Atom attribute is not well formed. Attribute '" << name << "' missing for data conversion";
415  FW_RAISE_EXCEPTION_IF( exception::ConversionNotManaged( msg.str() ), !atom );
416 
417  ::fwAtoms::Map::sptr mapAtom = ::fwAtoms::Map::dynamicCast(atom);
418 
419  for( ::fwAtoms::Map::ValueType elemAtom : mapAtom->getValue() )
420  {
421  if (!elemAtom.second)
422  {
423  FW_RAISE_EXCEPTION_IF( exception::ConversionNotManaged( "Not supported null element in Atom map." ),
424  property.elementType() != ::camp::userType );
425 
426  ::fwData::Object::sptr objectData;
427  property.set( m_campDataObj, elemAtom.first, objectData );
428  }
429  else
430  {
431  switch( elemAtom.second->type() )
432  {
433  case ::fwAtoms::Base::BOOLEAN:
434  case ::fwAtoms::Base::STRING:
435  {
436  std::string value = elemAtom.second->getString();
437  property.set( m_campDataObj, elemAtom.first, value );
438  break;
439  }
440  case ::fwAtoms::Base::NUMERIC:
441  {
442  ::fwAtoms::Numeric::sptr typedAtom = ::fwAtoms::Numeric::dynamicCast( elemAtom.second );
443  ::boost::apply_visitor( NumericMapPropertyVisitor(typedAtom, m_campDataObj, property,
444  elemAtom.first),
445  typedAtom->getVariant() );
446  break;
447  }
448  case ::fwAtoms::Base::OBJECT:
449  {
450  ::fwAtoms::Object::sptr objectAtom = ::fwAtoms::Object::dynamicCast(elemAtom.second);
451  ::fwData::Object::sptr objectData =
452  ::fwAtomConversion::convert( objectAtom, m_cache, m_uuidPolicy);
453  property.set( m_campDataObj, elemAtom.first, objectData );
454  break;
455  }
456  case ::fwAtoms::Base::BLOB:
457  {
458  ::fwAtoms::Blob::sptr blobAtom = ::fwAtoms::Blob::dynamicCast(elemAtom.second);
459  ::fwMemory::BufferObject::sptr buffer;
460  buffer = ::camp_ext::ValueMapper< ::fwAtoms::Blob::sptr >::to(blobAtom);
461  FW_RAISE_EXCEPTION_IF( exception::ConversionNotManaged(
462  "A blob cannot contain a null buffer pointer"),
463  !buffer );
464  property.set( m_campDataObj, elemAtom.first, ::camp::UserObject(buffer) );
465  break;
466  }
467  default:
468  {
469  std::stringstream msg;
470  msg << "fwAtoms::Map value elements of type '";
471  switch( elemAtom.second->type() )
472  {
473  case ::fwAtoms::Base::MAP:
474  msg << "MAP";
475  break;
476  case ::fwAtoms::Base::SEQUENCE:
477  msg << "SEQUENCE";
478  break;
479  default:
480  break;
481  }
482  msg <<"', are not supported in the data conversion process.";
483  FW_RAISE_EXCEPTION( exception::ConversionNotManaged(msg.str()) );
484  break;
485  }
486  }
487  }
488  }
489 }
490 
491 } // end namespace fwAtomConversion
FWATOMCONVERSION_API void visit(const camp::SimpleProperty &property)
Visits data object simple property and fill it with associated atom attribute.
virtual FWATOMCONVERSION_API ~AtomToDataMappingVisitor()
Destructor. Does nothing.
This namespace contains the necessary class for fwData <-> fwAtoms conversion.
Throw this exception when a conversion between data and atom is not managed (error message explains t...
Visitor UUID Management policies.
Definition: AtomVisitor.hpp:40
FWATOMCONVERSION_API AtomToDataMappingVisitor(std::shared_ptr< ::fwData::Object >dataObj, std::shared_ptr< ::fwAtoms::Object >atomObj, AtomVisitor::DataCacheType &cache, const AtomVisitor::IReadPolicy &uuidPolicy)
Constructor. Initializes visitor.
FWCAMP_API Type elementType() const
Get the type of the map elements.
Definition: MapProperty.cpp:57