1 //                                               -*- C++ -*-
2 /**
3  *  @brief Class PersistentObject saves and reloads the object's internal state
4  *
5  *  Copyright 2005-2021 Airbus-EDF-IMACS-ONERA-Phimeca
6  *
7  *  This library is free software: you can redistribute it and/or modify
8  *  it under the terms of the GNU Lesser General Public License as published by
9  *  the Free Software Foundation, either version 3 of the License, or
10  *  (at your option) any later version.
11  *
12  *  This library is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU Lesser General Public License for more details.
16  *
17  *  You should have received a copy of the GNU Lesser General Public License
18  *  along with this library.  If not, see <http://www.gnu.org/licenses/>.
19  *
20  */
21 #ifndef OPENTURNS_PERSISTENTOBJECT_HXX
22 #define OPENTURNS_PERSISTENTOBJECT_HXX
23 
24 #include "openturns/OSS.hxx"
25 #include "openturns/Object.hxx"
26 #include "openturns/StorageManager.hxx"
27 #include "openturns/IdFactory.hxx"
28 #include "openturns/Pointer.hxx"
29 
30 BEGIN_NAMESPACE_OPENTURNS
31 
32 
33 class StorageManager;
34 class Advocate;
35 template <class PERSISTENT> class Factory;
36 
37 /**
38  * @class PersistentObject
39  *
40  * @brief This class defines load and save mechanisms.
41  *
42  * This is the base class of all objects that can be stored into
43  * and reloaded from the study.
44  *
45  * The class defines an unique Id for every object so they can be
46  * equal but not identical. This Id is an essential part for the management
47  * of objects in studies.
48  * @sa Study
49  */
50 
51 class OT_API PersistentObject
52   : public Object
53 {
54 public:
55   CLASSNAME
56 
57   /**
58    * Default constructor
59    *
60    * The constructor sets a new Id to the object,
61    * so it can be later referenced by a Study object.
62    * It is also declared visible if member of a study.
63    *
64    * The object has the default name but it does not
65    * use storage for it.
66    */
PersistentObject()67   PersistentObject()
68     : p_name_(),
69       id_(0),
70       shadowedId_(id_),
71       studyVisible_(true)
72   {}
73 
74   /** Copy constructor */
PersistentObject(const PersistentObject & other)75   PersistentObject(const PersistentObject & other)
76     : p_name_(other.p_name_),
77       id_(0),
78       shadowedId_(other.shadowedId_),
79       studyVisible_(other.studyVisible_)
80   {}
81 
82   /**
83    * Virtual constructor
84    *
85    * @warning This method MUST be overloaded in derived classes.
86    * @return A pointer to a newly allocated object similar to this one
87    */
88   virtual PersistentObject * clone() const = 0;
89 
90   /** Destructor */
~PersistentObject()91   virtual ~PersistentObject() {}
92 
93   /** Assignment */
94   inline
operator =(const PersistentObject & other)95   PersistentObject & operator =(const PersistentObject & other)
96   {
97     if (this != &other)   // Other is NOT me, so I can assign it to me
98     {
99       p_name_ = other.p_name_;
100       studyVisible_ = other.studyVisible_;
101     }
102     return *this;
103   }
104 
105 
106   /**
107    * Comparison operator
108    *
109    * This method compares objects based on their content.
110    */
111   inline virtual
operator ==(const PersistentObject &) const112   Bool operator ==(const PersistentObject & /*other*/) const
113   {
114     return true;
115   }
116 
117   /**
118    * Comparison operator
119    *
120    * This method compares objects based on their content.
121    */
122   inline virtual
operator !=(const PersistentObject & other) const123   Bool operator !=(const PersistentObject & other) const
124   {
125     return !operator==(other);
126   }
127 
128   /**
129    * Identity comparator
130    *
131    * This method compares objects based on their Id.
132    * @return True if objects are the same
133    */
134   inline
is(const PersistentObject & other) const135   Bool is(const PersistentObject & other) const
136   {
137     return (getId() == other.getId());
138   }
139 
140   /* String converter */
141   inline
__repr__() const142   String __repr__() const override
143   {
144     return OSS() << "class=" << getClassName() << " name=" << getName();
145   }
146 
147   /* String converter */
148   inline
__str__(const String & offset="") const149   String __str__(const String & offset = "") const override
150   {
151     return OSS() << offset << __repr__();
152   }
153 
154 
155   /**
156    * Id accessor
157    * @return The id of this object
158    */
159   inline
getId() const160   Id getId() const
161   {
162     if (!id_)
163       id_ = IdFactory::BuildId();
164     return id_;
165   }
166 
167   /**
168    * Shadowed id accessor
169    * @internal
170    */
171   inline
setShadowedId(Id id)172   void setShadowedId(Id id)
173   {
174     shadowedId_ = id;
175   }
176   inline
getShadowedId() const177   Id getShadowedId() const
178   {
179     if (!shadowedId_)
180       shadowedId_ = getId();
181     return shadowedId_;
182   }
183 
184   /** Visibility accessor */
185   inline
setVisibility(Bool visible)186   void setVisibility(Bool visible)
187   {
188     studyVisible_ = visible;
189   }
190   inline
getVisibility() const191   Bool getVisibility() const
192   {
193     return studyVisible_;
194   }
195 
196   /**
197    * %Object name query
198    *
199    * This methos returns true if a name was given to the object
200    * @return True if object has a name
201    */
202   inline
hasName() const203   Bool hasName() const
204   {
205     return p_name_;
206   }
207 
208   /**
209    * %Object name visibility query
210    *
211    * This method returns true if a non-empty name was given to the object
212    * @return True if object has a non-empty name
213    */
214   inline
hasVisibleName() const215   Bool hasVisibleName() const
216   {
217     return (p_name_ && !p_name_->empty());
218   }
219 
220   /**
221    * %Object name accessor
222    *
223    * This method returns the name of the object if it has been previously set
224    * or the default name. Accessing the default name does not cause storage
225    * allocation as a side effect.
226    * @return The name of this object
227    */
228   inline
getName() const229   String getName() const
230   {
231     return ( hasName() ? *p_name_ : "Unnamed" );
232   }
233 
234   /**
235    * %Object name accessor
236    *
237    * This method sets \p name as the new name for the object. Setting the name
238    * may cause storage allocation for the new name, especially of the name was
239    * not defined so far.
240    * @param name The new name for this object
241    */
242   inline
setName(const String & name)243   void setName(const String & name)
244   {
245     if (name.empty()) p_name_.reset();
246     else p_name_.reset(new String(name));
247   }
248 
249 
250   /** Method save() stores the object through the StorageManager
251    * @internal
252    */
253   void save(StorageManager & mgr, const String & label, bool fromStudy = false) const;
254 
255   /** Method save() stores the object through the StorageManager
256    * @internal
257    */
258   void save(StorageManager & mgr, bool fromStudy = false) const;
259 
260   /** Method save() stores the object through the StorageManager
261    *
262    * @warning This method MUST be overloaded in derived classes.
263    * @internal
264    */
265   virtual void save(Advocate & adv) const;
266 
267   /** Method load() reloads the object from the StorageManager
268    *
269    * @warning This method MUST be overloaded in derived classes.
270    * @internal
271    */
272   virtual void load(Advocate & adv);
273 
274 
275 protected:
276 
277 private:
278 
279   /** The name of the object */
280   mutable Pointer<String> p_name_;
281 
282   /**
283    * The unique identifier of the object
284    *
285    * This identifier is needed when saving and reloading the object
286    * because it allows the chaining of objects even if they are
287    * relocated.
288    */
289   mutable Id id_;
290 
291   /**
292    * The shadowed id is used when object is reloaded. The object gets
293    * a new id that is almost always different from that stored in the study.
294    * So when we need to rebuild the objects dependency tree (ie, when
295    * object A embed object B), we have to make the id translation: the
296    * object holds the both ids, the new one (aka the Id as returned by getId)
297    * and the former one stored in the study (aka the shadowed id). This latter
298    * is never seen except by the object factory.
299    * @internal
300    */
301   mutable Id shadowedId_;
302 
303   /**
304    * This flag is used by the Study to know if the object should be displayed
305    * even if it had been added to the study (in particular, when the object
306    * was rebuild from file)
307    */
308   Bool studyVisible_;
309 
310 }; /* class PersistentObject */
311 
312 
313 END_NAMESPACE_OPENTURNS
314 
315 #endif /* OPENTURNS_PERSISTENTOBJECT_HXX */
316