fw4spl
CompareObjects.cpp
1 /* ***** BEGIN LICENSE BLOCK *****
2  * FW4SPL - Copyright (C) IRCAD, 2009-2017.
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 "fwDataCamp/visitor/CompareObjects.hpp"
8 
9 #include <fwCore/Exception.hpp>
10 
11 #include <fwData/camp/mapper.hpp>
12 
13 #include <fwMemory/BufferObject.hpp>
14 
15 #include <boost/functional/hash.hpp>
16 
17 #include <string>
18 
19 namespace fwDataCamp
20 {
21 
22 namespace visitor
23 {
24 
25 const std::string CompareObjects::s_MISSING_PROPERTY("CompareObjects::s_MISSING_PROPERTY");
26 
27 typedef CompareObjects::PropsMapType::value_type PropType;
28 
29 struct PropertyVisitor : public camp::ValueVisitor< PropType >
30 {
31  std::string m_prefix;
33 
34  PropertyVisitor(std::string prefix) :
35  m_prefix(prefix)
36  {
37  }
38 
39  PropertyVisitor(std::string prefix, SPTR(CompareObjects::PropsMapType)props) :
40  m_prefix(prefix),
41  m_props(props)
42  {
43  }
44 
45  //------------------------------------------------------------------------------
46 
47  PropType operator()(camp::NoType value)
48  {
49  return std::make_pair("", "");
50  }
51 
52  //------------------------------------------------------------------------------
53 
54  PropType operator()(bool value)
55  {
56  return std::make_pair(m_prefix, value ? "true" : "false");
57  }
58 
59  //------------------------------------------------------------------------------
60 
61  PropType operator()(long value)
62  {
63  return std::make_pair(m_prefix, ::boost::lexical_cast<std::string>(value));
64  }
65 
66  //------------------------------------------------------------------------------
67 
68  PropType operator()(double value)
69  {
70  return std::make_pair(m_prefix, ::boost::lexical_cast<std::string>(value));
71  }
72 
73  //------------------------------------------------------------------------------
74 
75  PropType operator()(const std::string& value)
76  {
77  return std::make_pair(m_prefix, value);
78  }
79 
80  //------------------------------------------------------------------------------
81 
82  PropType operator()(const camp::EnumObject& value)
83  {
84  return std::make_pair(m_prefix, value.name());
85  }
86 
87  //------------------------------------------------------------------------------
88 
89  PropType operator()(const camp::UserObject& value)
90  {
91  const camp::Class& metaclass = value.getClass();
92  PropType prop;
93 
94  if (value.pointer())
95  {
96  std::string classname = value.call("classname").to<std::string>();
97 
98  if (metaclass.name() != classname)
99  {
100  const camp::Class& newMetaclass = ::camp::classByName(classname);
101  CompareObjects visitor(value, m_prefix, m_props);
102  newMetaclass.visit(visitor);
103  }
104  else if(classname == "::fwMemory::BufferObject")
105  {
107  if(bo)
108  {
110  if(lock.getBuffer())
111  {
112  char* buffer = static_cast< char* >(lock.getBuffer());
113  std::size_t seed = 0;
114  const std::size_t buffsize = bo->getSize();
115  for(size_t i = 0; i < buffsize; ++i)
116  {
117  ::boost::hash_combine(seed, buffer[i]);
118  }
119  return std::make_pair(m_prefix, ::boost::lexical_cast< std::string >(seed));
120  }
121  }
122  }
123  else
124  {
125  CompareObjects visitor(value, m_prefix, m_props);
126  metaclass.visit(visitor);
127  }
128  }
129  else
130  {
131  OSLM_INFO("try visiting class= '" << metaclass.name() << " but a null pointer was found");
132  }
133  return prop;
134  }
135 };
136 
137 //-----------------------------------------------------------------------------
138 
140 {
141  m_props = SPTR(PropsMapType)(new PropsMapType);
142 }
143 
144 //-----------------------------------------------------------------------------
145 
147  const ::camp::UserObject& obj, const std::string& prefix, SPTR(PropsMapType)props) :
148  m_campObj(obj),
149  m_prefix(prefix),
150  m_props(props)
151 {
152 }
153 
154 //-----------------------------------------------------------------------------
155 
156 CompareObjects::~CompareObjects()
157 {
158 }
159 
160 //-----------------------------------------------------------------------------
161 
162 void CompareObjects::visit(const camp::SimpleProperty& property)
163 {
164  SLM_TRACE_FUNC();
165  const std::string name( property.name() );
166  OSLM_DEBUG("SimpleProperty name = " << name);
167  ::camp::Value elemValue = property.get(m_campObj);
168  PropertyVisitor visitor(getPath(name), m_props);
169  PropType pt = elemValue.visit(visitor);
170  if(!pt.first.empty())
171  {
172  m_props->insert(m_props->end(), pt);
173  }
174 }
175 
176 //-----------------------------------------------------------------------------
177 
178 void CompareObjects::visit(const camp::EnumProperty& property)
179 {
180  SLM_TRACE_FUNC();
181  const std::string name( property.name() );
182  ::camp::Value elemValue = property.get(m_campObj);
183 
184  PropertyVisitor visitor(getPath(name), m_props);
185  PropType pt = elemValue.visit(visitor);
186  if(!pt.first.empty())
187  {
188  m_props->insert(m_props->end(), pt);
189  }
190 }
191 
192 //-----------------------------------------------------------------------------
193 
194 void CompareObjects::visit(const camp::MapProperty& property)
195 {
196  SLM_TRACE_FUNC();
197  const std::string name(property.name());
198  OSLM_DEBUG("MapProperty name = " << name);
199 
200  std::pair< ::camp::Value, ::camp::Value > value;
201  std::string mapKey;
202  for (unsigned int i = 0; i < property.getSize(m_campObj); ++i)
203  {
204  value = property.getElement(m_campObj, i);
205  mapKey = value.first.to< std::string >();
206  PropertyVisitor visitor(getPath(name + "." + mapKey), m_props);
207  PropType pt = value.second.visit(visitor);
208  if(!pt.first.empty())
209  {
210  m_props->insert(m_props->end(), pt);
211  }
212  }
213 }
214 
215 //-----------------------------------------------------------------------------
216 
217 void CompareObjects::visit(const camp::ArrayProperty& property)
218 {
219  SLM_TRACE_FUNC();
220  const std::string name(property.name());
221  OSLM_DEBUG( "ArrayProperty name =" << name );
222 
223  for(unsigned int i = 0; i < property.size(m_campObj); ++i)
224  {
225  ::camp::Value elemValue = property.get(m_campObj, i);
226  std::stringstream ss;
227  ss << name << "." << i;
228  PropertyVisitor visitor(getPath(ss.str()), m_props);
229  PropType pt = elemValue.visit(visitor);
230  if(!pt.first.empty())
231  {
232  m_props->insert(m_props->end(), pt);
233  }
234  }
235 }
236 
237 //-----------------------------------------------------------------------------
238 
239 void CompareObjects::visit(const camp::UserProperty& property)
240 {
241  SLM_TRACE_FUNC();
242  const std::string name( property.name() );
243  OSLM_DEBUG( "UserProperty name =" << name );
244  ::camp::Value elemValue = property.get( m_campObj );
245 
246  if(m_campObj.call("is_a", ::camp::Args("::fwData::Object")).to<bool>())
247  {
248  PropertyVisitor visitor(getPath(name), m_props);
249  PropType pt = elemValue.visit(visitor);
250  if(!pt.first.empty())
251  {
252  m_props->insert(m_props->end(), pt);
253  }
254  }
255 }
256 
257 //-----------------------------------------------------------------------------
258 
259 void CompareObjects::visit(const camp::Function& function)
260 {
261  SLM_TRACE_FUNC();
262 }
263 
264 //-----------------------------------------------------------------------------
265 
266 std::string CompareObjects::getPath(const std::string& property) const
267 {
268  return m_prefix + (!m_prefix.empty() ? "." : "") + property;
269 }
270 
271 //-----------------------------------------------------------------------------
272 
274 {
275  if(objRef->getClassname() != objComp->getClassname())
276  {
277  std::stringstream ss;
278  ss << "Classnames mismatch : '" << objRef->getClassname() << "' (reference object) vs. '"
279  << objComp->getClassname() << "' (compared object)";
280  throw ::fwCore::Exception(ss.str());
281  }
282 
283  m_objRef = objRef;
284  m_objComp = objComp;
285 
286  SLM_ASSERT("Reference object not defined", m_objRef);
287  m_campObj = ::camp::UserObject(m_objRef.get());
288  const ::camp::Class& classRef = ::camp::classByName(m_objRef->getClassname());
289  classRef.visit(*this);
290  m_propsRef = std::move(*m_props);
291  m_props->clear();
292 
293  SLM_ASSERT("Reference object not defined", m_objComp);
294  m_campObj = ::camp::UserObject(m_objComp.get());
295  const ::camp::Class& classComp = ::camp::classByName(m_objComp->getClassname());
296  classComp.visit(*this);
297  m_propsComp = std::move(*m_props);
298  m_props->clear();
299 
300  for(PropsMapType::value_type prop : m_propsComp)
301  {
302  if(m_propsRef.find(prop.first) != m_propsRef.end())
303  {
304  if(m_propsRef[prop.first] != prop.second)
305  {
306  (*m_props)[prop.first] = prop.second;
307  }
308  }
309  else
310  {
311  (*m_props)[prop.first] = s_MISSING_PROPERTY;
312  }
313  }
314 
315  for(PropsMapType::value_type prop : m_propsRef)
316  {
317  if(m_propsComp.find(prop.first) == m_propsComp.end() && m_props->find(prop.first) == m_props->end())
318  {
319  (*m_props)[prop.first] = s_MISSING_PROPERTY;
320  }
321  }
322 }
323 
324 //-----------------------------------------------------------------------------
325 
326 } // visitor
327 
328 } // fwDataCamp
329 
#define SPTR(_cls_)
SizeType getSize() const
Returns the buffer&#39;s size.
FWDATACAMP_API CompareObjects()
Constructor.
#define SLM_TRACE_FUNC()
Trace contextual function signature.
Definition: spyLog.hpp:329
static FWDATACAMP_API const std::string s_MISSING_PROPERTY
Property value for differences map meaning a missing property.
virtual const std::string & getClassname() const override
return full object&#39;s classname with its namespace, i.e. fwCore::BaseObject
#define OSLM_INFO(message)
Definition: spyLog.hpp:252
Visitor used to compare two objects.
base class for BufferObject Lock
LockBase< T >::BufferType getBuffer() const
Returns BufferObject&#39;s buffer pointer.
This namespace contains data object descriptions used for introspection.
FWDATACAMP_API void compare(std::shared_ptr< ::fwData::Object > objRef, std::shared_ptr< ::fwData::Object > objComp)
Process to the comparison between reference object and compared object. When the process completes...
#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
Base class for each data object.
virtual FWMEMORY_API Lock lock()
Return a lock on the BufferObject.
Define Base class for FW4SPL buffers.
std::map< std::string, std::string > PropsMapType
Associates property path (within its parent object) to its value.
#define OSLM_DEBUG(message)
Definition: spyLog.hpp:241