1 /*
2  * Copyright 2006-2008 The FLWOR Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #pragma once
17 #ifndef ZORBA_BINARY_PLAN_ITERATOR_SERIALIZATION
18 #define ZORBA_BINARY_PLAN_ITERATOR_SERIALIZATION
19 
20 #include <time.h>
21 
22 #include "zorbamisc/config/platform.h"
23 
24 #include <string>
25 #include <list>
26 #include <vector>
27 #include <assert.h>
28 #include <iostream>
29 #include <typeinfo>
30 #include <string.h>
31 
32 #include "zorbaserialization/archiver_consts.h"
33 
34 namespace zorba
35 {
36 
37 class XQPCollator;
38 
39 namespace serialization
40 {
41 
42 class SerializeBaseClass;
43 class Archiver;
44 class MemArchiver;
45 class ClassDeserializer;
46 
47 
48 /*******************************************************************************
49 
50   The classes and macros defined in this file provide a generic infrastructure
51   for making an arbitrary c++ class serializable. This infrastructure is provided
52   for convenience; not every c++ type has to adopt this inftrasture. Class that
53   do follow this infrastructure can be serialized via the template operators:
54 
55   void operator&(Archiver& ar, T& obj) and
56   void operator&(Archiver& ar, T*& obj),
57 
58   which are defined in serialize_template_types.h. These operators assume that
59   T is a class that has the following 2 methods:
60 
61   get_class_name_str() and serialize_internal()
62 ********************************************************************************/
63 
64 
65 /*******************************************************************************
66   There is only one global instance of this class.
67 
68   theClassFactories:
69   ------------------
70   This map associates the name of a class C with a pointer to the ClassDeserializer
71   obj associated with C (if any such obj actually exists). The map is populated
72   "automatically", during the instantiation of each ClassDeserializer obj; the
73   constructor of each such obj places an entry into the map.
74 
75   harcoded_objects_archive:
76   -------------------------
77 
78 ********************************************************************************/
79 class ClassSerializer
80 {
81   friend class Archiver;
82 
83 typedef std::vector<ClassDeserializer*> ClassFactoriesMap;
84 
85 public:
86   static const unsigned long g_zorba_classes_version;
87 
88 private:
89   ClassFactoriesMap     theClassFactories;
90 
91   MemArchiver         * harcoded_objects_archive;
92 
93 public:
94   clock_t   t0;
95   clock_t   t1;
96 
97 public:
98   static ClassSerializer* getInstance();
99 
100 public:
101   ClassSerializer();
102 
103   ~ClassSerializer();
104 
105   void register_class_factory(TypeCode code, ClassDeserializer* d);
106 
107   ClassDeserializer* get_class_factory(TypeCode code);
108 
109   Archiver* getArchiverForHardcodedObjects();
110 
111   void destroyArchiverForHardcodedObjects();
112 
get_registration_time()113   clock_t get_registration_time() { return t1 - t0; }
114 };
115 
116 
117 /*******************************************************************************
118   A class that may be used as the base for other c++ classes that need to be
119   serialized.
120 
121   The serialize_internal() method is called by the template operators:
122   void operator&(Archiver& ar, T& obj) and
123   void operator&(Archiver& ar, T*& obj).
124 
125 ********************************************************************************/
126 class ZORBA_DLL_PUBLIC SerializeBaseClass
127 {
128 public:
~SerializeBaseClass()129   virtual ~SerializeBaseClass() {}
130 
131   virtual serialization::TypeCode get_serializer_type_code() const = 0;
132 
133   virtual void serialize_internal(Archiver& ar) = 0;
134 };
135 
136 
137 /*******************************************************************************
138   Every serializable class C has a nested member class D that is a subclass of
139   ClassDeserializer. Furthermore, every serializable class has a static data
140   member of type D, whose initilization (via its default constructor) causes
141   class C to be registered in the global ClassSerializer instance.
142 ********************************************************************************/
143 class ClassDeserializer
144 {
145 public:
~ClassDeserializer()146   virtual ~ClassDeserializer() { }
147 
148   virtual SerializeBaseClass* create_new(Archiver& ar) = 0;
149 };
150 
151 
152 #define SERIALIZABLE_CLASS_FACTORY_DECL(class_name, creator)            \
153 template<class T_serialized_class>                                      \
154 class class_factory : public ::zorba::serialization::ClassDeserializer  \
155 {                                                                       \
156 public:                                                                 \
157   class_factory()                                                       \
158   {                                                                     \
159     serialization::ClassSerializer::getInstance()->                     \
160     register_class_factory(T_serialized_class::get_serializer_type_code_static(), this); \
161   }                                                                     \
162                                                                         \
163   virtual serialization::SerializeBaseClass* create_new(serialization::Archiver& ar) \
164   {                                                                     \
165     return creator;                                                     \
166   }                                                                     \
167 };
168 
169 
170 /*******************************************************************************
171 
172 ********************************************************************************/
173 #define SERIALIZABLE_CLASS(class_name)                                   \
174   virtual void serialize_internal(::zorba::serialization::Archiver& ar); \
175                                                                          \
176   static serialization::TypeCode theTypeCode;                            \
177                                                                          \
178   virtual serialization::TypeCode get_serializer_type_code() const       \
179   {                                                                      \
180     return theTypeCode;                                                  \
181   }                                                                      \
182                                                                          \
183   static serialization::TypeCode get_serializer_type_code_static()       \
184   {                                                                      \
185     return theTypeCode;                                                  \
186   }                                                                      \
187                                                                          \
188   SERIALIZABLE_CLASS_FACTORY_DECL(class_name, new class_name(ar))        \
189   static class_factory<class_name>  g_class_factory;                     \
190 
191 
192 #define SERIALIZABLE_ABSTRACT_CLASS(class_name)                          \
193   virtual void serialize_internal(::zorba::serialization::Archiver& ar); \
194                                                                          \
195   virtual serialization::TypeCode get_serializer_type_code() const       \
196   {                                                                      \
197     return serialization::TYPE_LAST;                                     \
198   }
199 
200 
201 #define SERIALIZE_INTERNAL_METHOD(class_name)                             \
202 void class_name::serialize_internal(::zorba::serialization::Archiver& ar) \
203 {                                                                         \
204   if (ar.is_serialize_base_class())                                       \
205     ar.set_serialize_base_class(false);                                   \
206                                                                           \
207   class_name::serialize(ar);                                              \
208 }
209 
210 
211 #define SERIALIZABLE_CLASS_VERSIONS(class_name)                             \
212   serialization::TypeCode class_name::theTypeCode =                         \
213     serialization::TYPE_##class_name;                                       \
214                                                                             \
215   class_name::class_factory<class_name> class_name::g_class_factory;        \
216                                                                             \
217   SERIALIZE_INTERNAL_METHOD(class_name)
218 
219 
220 #define SERIALIZABLE_CLASS_VERSIONS_2(class_name, type_code)                \
221   serialization::TypeCode class_name::theTypeCode =                         \
222     serialization::type_code;                                               \
223                                                                             \
224   class_name::class_factory<class_name> class_name::g_class_factory;        \
225                                                                             \
226   SERIALIZE_INTERNAL_METHOD(class_name)
227 
228 
229 /*******************************************************************************
230 
231 ********************************************************************************/
232 
233 #define SERIALIZABLE_TEMPLATE_CLASS(class_name)                         \
234   virtual void serialize_internal(::zorba::serialization::Archiver& ar) \
235   {                                                                     \
236     if (ar.is_serialize_base_class())                                   \
237       ar.set_serialize_base_class(false);                               \
238                                                                         \
239     class_name::serialize(ar);                                          \
240   }                                                                     \
241                                                                         \
242   static serialization::TypeCode theTypeCode;                           \
243                                                                         \
244   virtual serialization::TypeCode get_serializer_type_code() const      \
245   {                                                                     \
246     return theTypeCode;                                                 \
247   }                                                                     \
248                                                                         \
249   static serialization::TypeCode get_serializer_type_code_static()      \
250   {                                                                     \
251     return theTypeCode;                                                 \
252   }                                                                     \
253                                                                         \
254   SERIALIZABLE_CLASS_FACTORY_DECL(class_name, new class_name(ar))
255 
256 
257 #define SERIALIZABLE_TEMPLATE_ABSTRACT_CLASS(class_name)                \
258   virtual void serialize_internal(::zorba::serialization::Archiver& ar) \
259   {                                                                     \
260     if (ar.is_serialize_base_class())                                   \
261       ar.set_serialize_base_class(false);                               \
262                                                                         \
263     class_name::serialize(ar);                                          \
264   }                                                                     \
265                                                                         \
266   virtual serialization::TypeCode get_serializer_type_code() const      \
267   {                                                                     \
268     return serialization::TYPE_LAST;                                    \
269   }
270 
271 
272 //
273 // Static members of template classes with one template param.
274 //
275 // The "index" param of the macro is used as a unique id for each specific
276 // instantiation of the template class.
277 //
278 // Example:
279 //
280 // SERIALIZABLE_TEMPLATE_INSTANCE_VERSIONS(
281 //     TypedValueCompareIterator,
282 //     TypedValueCompareIterator<store::XS_DOUBLE>,
283 //     1)
284 //
285 #define SERIALIZABLE_TEMPLATE_INSTANCE(template_name, instance_name, index) \
286                                                                             \
287 instance_name::class_factory<instance_name>                                 \
288 g_class_factory_##template_name##_##index;                                  \
289                                                                             \
290 template<> serialization::TypeCode instance_name::theTypeCode =             \
291 serialization::TYPE_##template_name##_##index;
292 
293 //
294 //  If the template class has more than one template params, e.g. Foo<T1, T2>,
295 //  then we need this macro because we cannot pass Foo<T1, T2> as the instance_name
296 //  param of the SERIALIZABLE_TEMPLATE_INSTANCE_VERSIONS macro. This is because
297 //  the "," inside Foo<T1, T2> will make it appear as two params.
298 //
299 //  Example:
300 //
301 // SERIALIZABLE_TEMPLATE_INSTANCE_VERSIONS2(
302 //     serializable_HashEntry,
303 //     serializable_HashEntry<store::Item*,
304 //     StaticallyKnownCollection_t>,
305 //     1)
306 //
307 #define SERIALIZABLE_TEMPLATE_INSTANCE_2(template_name, instance_name, second_T, index) \
308                                                                           \
309 instance_name, second_T::class_factory<instance_name,second_T>            \
310 g_class_factory_##template_name##_##index;                                \
311                                                                           \
312 template<> serialization::TypeCode instance_name, second_T::theTypeCode = \
313 serialization::TYPE_##template_name##_##index;
314 
315 
316 /*******************************************************************************
317   Constructors to be used during deserialization
318 ********************************************************************************/
319 
320 #define SERIALIZABLE_CLASS_CONSTRUCTOR(class_name) \
321 class_name(::zorba::serialization::Archiver& ar)   \
322   :                                                \
323   ::zorba::serialization::SerializeBaseClass()     \
324 {                                                  \
325 }
326 
327 #define SERIALIZABLE_CLASS_CONSTRUCTOR2(class_name, base_class) \
328 class_name(::zorba::serialization::Archiver& ar)                \
329   :                                                             \
330   base_class(ar)                                                \
331 {                                                               \
332 }
333 
334 #define SERIALIZABLE_CLASS_CONSTRUCTOR2_NULL_PARAM1(class_name, base_class, param1) \
335 class_name(::zorba::serialization::Archiver& ar)                \
336   :                                                             \
337   base_class(ar),                                               \
338   param1(NULL)                                                  \
339 {                                                               \
340 }
341 
342 #define SERIALIZABLE_CLASS_CONSTRUCTOR2_NULL_PARAM2(class_name, base_class, param1, param2) \
343 class_name(::zorba::serialization::Archiver& ar)                \
344   :                                                             \
345   base_class(ar),                                               \
346   param1(NULL),                                                 \
347   param2(NULL)                                                  \
348 {                                                               \
349 }
350 
351 
352 #define SERIALIZABLE_CLASS_CONSTRUCTOR3(class_name, base_class1, base_class2) \
353 class_name(::zorba::serialization::Archiver& ar)                              \
354   :                                                                           \
355   base_class1(ar),                                                            \
356   base_class2(ar)                                                             \
357 {                                                                             \
358 }
359 
360 //
361 // Example:
362 //
363 // SERIALIZABLE_CLASS_CONSTRUCTOR2T(SequentialIterator,
364 // NaryBaseIterator<SequentialIterator, PlanIteratorState>);
365 //
366 #define SERIALIZABLE_CLASS_CONSTRUCTOR2T(class_name, base_class, templ2) \
367 class_name(::zorba::serialization::Archiver& ar)                         \
368   :                                                                      \
369   base_class , templ2(ar)                                                \
370 {                                                                        \
371 }
372 
373 
374 //
375 // Example:
376 //
377 // SERIALIZABLE_CLASS_CONSTRUCTOR3T(SpecificNumArithIterator,
378 // BinaryBaseIterator<SpecificNumArithIterator<Operation, Type>, PlanIteratorState>);
379 //
380 #define SERIALIZABLE_CLASS_CONSTRUCTOR3T(class_name, base_class, templ2, templ3) \
381 class_name(::zorba::serialization::Archiver& ar)                                 \
382   :                                                                              \
383   base_class , templ2, templ3(ar)                                                \
384 {                                                                                \
385 }
386 
387 } // namespace serialization
388 } // namespace zorba
389 
390 #endif
391 /*
392  * Local variables:
393  * mode: c++
394  * End:
395  */
396 /* vim:set et sw=2 ts=2: */
397