libcrn  3.9.5
A document image processing library
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CRNSavable.cpp
Go to the documentation of this file.
1 /* Copyright 2006-2016 INSA Lyon, CoReNum, ENS-Lyon
2  *
3  * This file is part of libcrn.
4  *
5  * libcrn is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU Lesser General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * libcrn is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with libcrn. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * file: CRNSavable.cpp
19  * \author Yann LEYDIER
20  */
21 
22 #include <CRNi18n.h>
23 #include <CRNSavable.h>
24 #include <CRNException.h>
25 #include <CRNData/CRNMap.h>
26 #include <CRNXml/CRNXml.h>
27 
28 using namespace crn;
29 
30 const StringUTF8 USERDATA_NAME("userdata");
31 
37  name(s),
38  user_data(nullptr),
39  filelock(std::make_unique<std::mutex>()),
40  filename("")
41 {
42 }
43 
48 {
49 }
50 
51 Savable::Savable(Savable&&) noexcept = default;
52 Savable& Savable::operator=(Savable&&c) = default;
53 
54 /*****************************************************************************/
61 bool Savable::IsUserData(const String &key) const
62 {
63  if (!user_data)
64  return false;
65  if (user_data->Find(key) != user_data->end())
66  return true;
67  else
68  return false;
69 }
70 
71 /*****************************************************************************/
78 SObject Savable::GetUserData(const String &key)
79 {
80  if (!user_data)
81  return nullptr;
82  if (IsUserData(key))
83  return (*user_data)[key];
84  else
85  return nullptr;
86 }
87 
88 /*****************************************************************************/
95 String Savable::GetUserDataKey(const SObject &value) const
96 {
97  if (!user_data)
98  return U"";
99  for (Map::const_iterator it = user_data->begin(); it != user_data->end(); ++it)
100  {
101  if (it->second == value)
102  return it->first;
103  }
104  return U"";
105 }
106 
107 /*****************************************************************************/
114 const SObject Savable::GetUserData(const String &key) const
115 {
116  if (!user_data)
117  return nullptr;
118  if (IsUserData(key))
119  return (*user_data)[key];
120  else
121  return nullptr;
122 }
123 
124 /*****************************************************************************/
133 {
134  if (!user_data)
135  throw ExceptionNotFound(_("No user data to remove."));
136  user_data->Remove(key); // may throw
137 }
138 
145 void Savable::SetUserData(const String &key, SObject value)
146 {
147  if (!user_data)
148  user_data.reset(new Map());
149  user_data->Set(key, value);
150 }
151 
156 {
157  if (user_data)
158  user_data->Clear();
159 }
160 
161 /***************************************************************************/
162 /* Savable informal protocol */
163 /***************************************************************************/
170 Savable::Savable(const String &s, const Path &fname):
171  name(s),
172  user_data(nullptr),
173  filelock(std::make_unique<std::mutex>()),
174  filename(fname)
175 {
176 }
177 
188 void Savable::Load(const Path &fname)
189 {
190  std::lock_guard<std::mutex> lock(*filelock);
191  Path fn;
192  if (fname.IsAbsolute())
193  fn = fname;
194  else
195  fn = completeFilename(fname);
196  load(fn);
197  filename = fname;
198 }
199 
208 void Savable::Save(const Path &fname)
209 {
210  std::lock_guard<std::mutex> lock(*filelock);
211  Path fn;
212  if (fname.IsAbsolute())
213  fn = fname;
214  else
215  fn = completeFilename(fname);
216  save(fn);
217  filename = fname;
218 }
219 
228 {
229  if (filename.IsEmpty())
230  return throw ExceptionUninitialized(_("Cannot save an object with no filename."));
231  Save(filename);
232 }
233 
241 Path Savable::completeFilename(const Path &fn) const
242 {
243  return fn;
244 }
245 
258 void Savable::load(const Path &fname)
259 {
260  throw ExceptionProtocol(StringUTF8("load() not implemented in ") + typeid(*this).name());
261 }
262 
271 void Savable::save(const Path &fname)
272 {
273  throw ExceptionProtocol(StringUTF8("save() not implemented in ") + typeid(*this).name());
274 }
275 
276 /*****************************************************************************/
283 {
284  // read name if any
285  const StringUTF8 nam = el.GetAttribute<StringUTF8>("name");
286 
287  xml::Element udel(el.GetFirstChildElement("Map"));
288  while (udel)
289  { // look for a map containing user data
290  const StringUTF8 role = udel.GetAttribute<StringUTF8>("role");
291  // check role
292  if (role == USERDATA_NAME)
293  { // found the user data
294  if (!user_data)
295  { // create the object if needed
296  user_data.reset(new Map());
297  }
298  else
299  { // clear the current user data if needed
300  user_data->Clear();
301  }
302  // read the user data and quit the method
303  user_data->Deserialize(udel);
304  return;
305  }
306  udel = udel.GetNextSiblingElement("Map");
307  }
308 }
309 
310 /*****************************************************************************/
317 {
318  el.SetAttribute("name", name.CStr());
319  if (user_data)
320  {
321  xml::Element udel = user_data->Serialize(el);
322  udel.SetAttribute("role", USERDATA_NAME);
323  }
324 }
325 
326 
XML element.
Definition: CRNXml.h:135
complex base abstract class
Definition: CRNSavable.h:58
#define _(String)
Definition: CRNi18n.h:51
bool IsUserData(const String &key) const
Tests if a user data key exists.
Definition: CRNSavable.cpp:61
const char * CStr() const
Conversion to UTF8 cstring.
Definition: CRNString.cpp:167
Unintialized object error.
Definition: CRNException.h:155
std::unique_ptr< std::mutex > filelock
Definition: CRNSavable.h:122
const StringUTF8 USERDATA_NAME("userdata")
void serialize_internal_data(xml::Element &el) const
Dumps some internal data to an XML element.
Definition: CRNSavable.cpp:316
void Load(const Path &fname)
Loads the object from an XML file (Safe)
Definition: CRNSavable.cpp:188
virtual ~Savable()
Destructor.
Definition: CRNSavable.cpp:47
A UTF32 character string class.
Definition: CRNString.h:61
bool IsAbsolute() const
Is the path absolute?
Definition: CRNPath.cpp:173
A protocol is not implemented.
Definition: CRNException.h:143
void SetUserData(const String &key, SObject value)
Adds or replaces a user data.
Definition: CRNSavable.cpp:145
Element GetFirstChildElement(const StringUTF8 &name="")
Gets the first child element.
Definition: CRNXml.cpp:320
bool IsEmpty() const noexcept
Checks if the string is empty.
A convenience class for file paths.
Definition: CRNPath.h:39
String GetUserDataKey(const SObject &value) const
Gets a user data key by value.
Definition: CRNSavable.cpp:95
void ClearUserData()
Deletes all user data entries.
Definition: CRNSavable.cpp:155
void SetAttribute(const StringUTF8 &name, const StringUTF8 &value)
Sets the value of an attribute.
Definition: CRNXml.cpp:595
std::map< String, SObject >::const_iterator const_iterator
const_iterator on the contents of the container
Definition: CRNMap.h:93
void Save()
Saves the object to an already set XML file.
Definition: CRNSavable.cpp:227
SObject GetUserData(const String &key)
Gets a user data by key.
Definition: CRNSavable.cpp:78
T GetAttribute(const StringUTF8 &name, bool silent=true) const
Gets an attribute.
Definition: CRNXml.h:219
void DeleteUserData(const String &key)
Deletes a user data entry and frees the value.
Definition: CRNSavable.cpp:132
Data map class.
Definition: CRNMap.h:42
A character string class.
Definition: CRNStringUTF8.h:49
void deserialize_internal_data(xml::Element &el)
Initializes some internal data from an XML element.
Definition: CRNSavable.cpp:282
Savable(const String &s=U"")
Default constructor.
Definition: CRNSavable.cpp:36
An item was not found in a container.
Definition: CRNException.h:95