fw4spl
Field.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 "fwDataTools/helper/Field.hpp"
8 
9 #include <fwCom/Signal.hxx>
10 
11 #include <fwData/Exception.hpp>
12 #include <fwData/Object.hpp>
13 
14 #include <algorithm>
15 #include <functional>
16 
17 namespace fwDataTools
18 {
19 namespace helper
20 {
21 
22 //-----------------------------------------------------------------------------
23 
24 Field::Field( ::fwData::Object::sptr object ) :
25  m_object( object )
26 {
27 }
28 
29 //-----------------------------------------------------------------------------
30 
32 {
33  if(!m_addedFields.empty() || !m_newChangedFields.empty() || !m_removedFields.empty() )
34  {
35  notify();
36  }
37 }
38 
39 //-----------------------------------------------------------------------------
40 
41 void Field::setField(const fwData::Object::FieldNameType& name, fwData::Object::sptr obj)
42 {
43  this->addOrSwap(name, obj);
44 }
45 
46 //-----------------------------------------------------------------------------
47 
48 void Field::setFields( const fwData::Object::FieldMapType& newFields)
49 {
50  ::fwData::Object::sptr object = m_object.lock();
51  SLM_ASSERT("Field helper need a non-null object pointer", object);
52  const ::fwData::Object::FieldMapType oldFields = object->getFields();
53  this->buildMessage(oldFields, newFields);
54  object->setFields(newFields);
55 }
56 
57 //-----------------------------------------------------------------------------
58 
59 void Field::removeField(const fwData::Object::FieldNameType& name)
60 {
61  this->remove(name);
62 }
63 
64 //-----------------------------------------------------------------------------
65 
66 void Field::add(const fwData::Object::FieldNameType& _name, fwData::Object::sptr _obj)
67 {
68  ::fwData::Object::sptr object = m_object.lock();
69  SLM_ASSERT("Field helper need a non-null object pointer", object);
70 
71  ::fwData::Object::sptr field = object->getField(_name);
72  FW_RAISE_EXCEPTION_IF(::fwData::Exception("Field already exists"), field);
73 
74  m_addedFields[_name] = _obj;
75 
76  object->setField(_name, _obj);
77 }
78 
79 //-----------------------------------------------------------------------------
80 
81 void Field::swap(const fwData::Object::FieldNameType& _name, fwData::Object::sptr _obj)
82 {
83  SLM_ASSERT("Field helper need a non-null object pointer", !m_object.expired());
84  ::fwData::Object::sptr object = m_object.lock();
85 
86  ::fwData::Object::sptr field = object->getField(_name);
87  FW_RAISE_EXCEPTION_IF(::fwData::Exception("Field does not exist"), !field);
88 
89  m_newChangedFields[_name] = _obj;
90  m_oldChangedFields[_name] = field;
91 
92  object->setField(_name, _obj);
93 }
94 
95 //-----------------------------------------------------------------------------
96 
97 void Field::addOrSwap(const fwData::Object::FieldNameType& _name, fwData::Object::sptr _obj)
98 {
99  SLM_ASSERT("Field helper need a non-null object pointer", !m_object.expired());
100  ::fwData::Object::sptr object = m_object.lock();
101 
102  ::fwData::Object::sptr field = object->getField(_name);
103 
104  if (!field)
105  {
106  m_addedFields[_name] = _obj;
107  }
108  else
109  {
110  m_newChangedFields[_name] = _obj;
111  m_oldChangedFields[_name] = field;
112  }
113  object->setField(_name, _obj);
114 }
115 
116 //-----------------------------------------------------------------------------
117 
118 void Field::remove(const fwData::Object::FieldNameType& _name)
119 {
120  SLM_ASSERT("Field helper need a non-null object pointer", !m_object.expired());
121  ::fwData::Object::sptr object = m_object.lock();
122  ::fwData::Object::sptr field = object->getField(_name);
123 
124  FW_RAISE_EXCEPTION_IF(::fwData::Exception("Field does not exist"), !field);
125 
126  m_removedFields[_name] = field;
127  object->removeField(_name);
128 }
129 
130 //-----------------------------------------------------------------------------
131 
133 {
134  SLM_ASSERT("Field helper need a non-null object pointer", !m_object.expired());
135  ::fwData::Object::sptr object = m_object.lock();
136 
137  auto fieldNames = object->getFieldNames();
138  for(const auto& name : fieldNames)
139  {
140  ::fwData::Object::sptr field = object->getField(name);
141  m_removedFields[name] = field;
142  object->removeField(name);
143  }
144 }
145 
146 //-----------------------------------------------------------------------------
147 
149 {
150  SLM_ASSERT("Field helper need a non-null object pointer", !m_object.expired());
151 
152  if ( !m_removedFields.empty() )
153  {
154  auto sig = m_object.lock()->signal< ::fwData::Object::RemovedFieldsSignalType >(
156 
157  sig->asyncEmit(m_removedFields);
158  }
159  if ( !m_newChangedFields.empty() && !m_oldChangedFields.empty() )
160  {
161  auto sig = m_object.lock()->signal< ::fwData::Object::ChangedFieldsSignalType >(
163 
164  sig->asyncEmit(m_newChangedFields, m_oldChangedFields);
165  }
166  if ( !m_addedFields.empty() )
167  {
168  auto sig = m_object.lock()->signal< ::fwData::Object::AddedFieldsSignalType >(
170 
171  sig->asyncEmit(m_addedFields);
172  }
173  OSLM_INFO_IF("No changes were found on the fields of the object '" + m_object.lock()->getID()
174  + "', nothing to notify.",
175  m_addedFields.empty() && m_newChangedFields.empty() && m_removedFields.empty());
176 
177  m_removedFields.clear();
178  m_newChangedFields.clear();
179  m_oldChangedFields.clear();
180  m_addedFields.clear();
181 }
182 
183 //-----------------------------------------------------------------------------
184 
185 void Field::buildMessage(const ::fwData::Object::FieldMapType& oldFields,
186  const ::fwData::Object::FieldMapType& newFields)
187 {
188  ::fwData::Object::FieldNameVectorType oldFieldNames;
189  ::fwData::Object::FieldNameVectorType newFieldNames;
190 
191  std::transform(
192  oldFields.begin(), oldFields.end(),
193  std::back_inserter(oldFieldNames),
194  std::bind(&::fwData::Object::FieldMapType::value_type::first, std::placeholders::_1)
195  );
196  std::transform(
197  newFields.begin(), newFields.end(),
198  std::back_inserter(newFieldNames),
199  std::bind(&::fwData::Object::FieldMapType::value_type::first, std::placeholders::_1)
200  );
201 
202  std::sort(oldFieldNames.begin(), oldFieldNames.end());
203  std::sort(newFieldNames.begin(), newFieldNames.end());
204 
205  ::fwData::Object::FieldNameVectorType added; // new - old
206  ::fwData::Object::FieldNameVectorType changed; // old & new
207  ::fwData::Object::FieldNameVectorType removed; // old - new
208 
209  std::set_difference(
210  newFieldNames.begin(), newFieldNames.end(),
211  oldFieldNames.begin(), oldFieldNames.end(),
212  std::back_inserter(added)
213  );
214 
215  std::set_intersection(
216  newFieldNames.begin(), newFieldNames.end(),
217  oldFieldNames.begin(), oldFieldNames.end(),
218  std::back_inserter(changed)
219  );
220 
221  std::set_difference(
222  oldFieldNames.begin(), oldFieldNames.end(),
223  newFieldNames.begin(), newFieldNames.end(),
224  std::back_inserter(removed)
225  );
226 
227  for(const ::fwData::Object::FieldNameVectorType::value_type& fieldName : added)
228  {
229  m_addedFields[fieldName] = newFields.find(fieldName)->second;
230  }
231 
232  for(const ::fwData::Object::FieldNameVectorType::value_type& fieldName : changed)
233  {
234  m_newChangedFields[fieldName] = newFields.find(fieldName)->second;
235  m_oldChangedFields[fieldName] = oldFields.find(fieldName)->second;
236  }
237 
238  for(const ::fwData::Object::FieldNameVectorType::value_type& fieldName : removed)
239  {
240  m_removedFields[fieldName] = oldFields.find(fieldName)->second;
241  }
242 }
243 
244 } // namespace helper
245 } // namespace fwDataTools
FWDATATOOLS_API Field(::fwData::Object::sptr object)
Constructor. Initialize parameters.
Definition: Field.cpp:24
FWDATATOOLS_API void add(const ::fwData::Object::FieldNameType &_name,::fwData::Object::sptr _obj)
Add a field in the object.
Definition: Field.cpp:66
::fwData::Object::FieldsContainerType m_addedFields
Map of added objects, send on notify.
Definition: Field.hpp:117
FWDATATOOLS_API void addOrSwap(const ::fwData::Object::FieldNameType &_name,::fwData::Object::sptr _obj)
Add or replace a field in the object.
Definition: Field.cpp:97
The namespace fwDataTools contains classes which provide helpers to manipulate fwData::Object. *.
Implements data exception class.
FWDATATOOLS_API void removeField(const ::fwData::Object::FieldNameType &name)
Removes field with specified name.
Definition: Field.cpp:59
#define OSLM_INFO_IF(message, cond)
Definition: spyLog.hpp:256
FWDATATOOLS_API void notify()
Send the built message and clear the internal maps.
Definition: Field.cpp:148
static FWDATA_APIconst::fwCom::Signals::SignalKeyType s_CHANGED_FIELDS_SIG
Type of signal m_sigModified.
static FWDATA_APIconst::fwCom::Signals::SignalKeyType s_ADDED_FIELDS_SIG
Type of signal m_sigModified.
FWDATATOOLS_API void clear()
Clear all fields in the object.
Definition: Field.cpp:132
::fwData::Object::FieldsContainerType m_newChangedFields
Map of new changed objects, send on notify.
Definition: Field.hpp:119
FWDATATOOLS_API void remove(const ::fwData::Object::FieldNameType &_name)
Remove a field from the object.
Definition: Field.cpp:118
::fwData::Object::FieldsContainerType m_removedFields
Map of removed objects, send on notify.
Definition: Field.hpp:123
#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
FWDATATOOLS_API void setField(const ::fwData::Object::FieldNameType &name,::fwData::Object::sptr obj)
Register field with specified name. If the name does already exist, the matching field will be replac...
Definition: Field.cpp:41
static FWDATA_APIconst::fwCom::Signals::SignalKeyType s_REMOVED_FIELDS_SIG
Type of signal m_sigModified.
FWDATATOOLS_API void swap(const ::fwData::Object::FieldNameType &_name,::fwData::Object::sptr _obj)
Replace a field in the object.
Definition: Field.cpp:81
::fwData::Object::FieldsContainerType m_oldChangedFields
Map of old changed objects, send on notify.
Definition: Field.hpp:121
FWDATATOOLS_API ~Field()
Destructor. Call notify if changes has been made.
Definition: Field.cpp:31
FWDATATOOLS_API void setFields(const ::fwData::Object::FieldMapType &newFields)
Replace the field map content.
Definition: Field.cpp:48
::fwData::Object::wptr m_object
Composite to add/remove/change objects.
Definition: Field.hpp:126