1-----------------------------------------------------------------------
2--  Util.Beans.Objects -- Generic Typed Data Representation
3--  Copyright (C) 2009, 2010, 2011, 2013 Stephane Carrez
4--  Written by Stephane Carrez (Stephane.Carrez@gmail.com)
5--
6--  Licensed under the Apache License, Version 2.0 (the "License");
7--  you may not use this file except in compliance with the License.
8--  You may obtain a copy of the License at
9--
10--      http://www.apache.org/licenses/LICENSE-2.0
11--
12--  Unless required by applicable law or agreed to in writing, software
13--  distributed under the License is distributed on an "AS IS" BASIS,
14--  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15--  See the License for the specific language governing permissions and
16--  limitations under the License.
17-----------------------------------------------------------------------
18
19--  Provides a data type to manage entities of different types using the
20--  same abstraction.
21--
22--  An ''Object' can hold one of the following values:
23--   o a boolean
24--   o a long long integer
25--   o a date
26--   o a string
27--   o a wide wide string
28--   o a generic data
29--
30--
31--  Value : Object := To_Object ("something");
32--  Value := Value + To_Object ("12");
33--
34with Ada.Strings.Unbounded;
35with Ada.Strings.Wide_Wide_Unbounded;
36with Ada.Finalization;
37private with Util.Concurrent.Counters;
38limited with Util.Beans.Basic;
39package Util.Beans.Objects is
40
41   pragma Preelaborate;
42
43   use Ada.Strings.Unbounded;
44   use Ada.Strings.Wide_Wide_Unbounded;
45
46   --  Exception raised when an object cannot be converted to a given type.
47   Conversion_Error : exception;
48
49   type Data_Type is (TYPE_NULL,
50                      --  The object holds a boolean value.
51                      TYPE_BOOLEAN,
52                      --  The object holds an integer value (64-bits).
53                      TYPE_INTEGER,
54                      --  The object holds a floating point value.
55                      TYPE_FLOAT,
56                      --  The object holds a date and time
57                      TYPE_TIME,
58                      --  The object holds a string
59                      TYPE_STRING,
60                      --  The object holds a wide wide string
61                      TYPE_WIDE_STRING,
62                      --  The object holds a generic bean
63                      TYPE_BEAN);
64
65   type Storage_Type is (STATIC, DYNAMIC);
66
67   --  Exception raised when the value identified by a name is not
68   --  recognized.
69   No_Value : exception;
70
71   --  ------------------------------
72   --  Generic Object holding a value
73   --  ------------------------------
74   --  The object has a type represented by 'Object_Type'.
75   --  It can hold any value while being tightly coupled with a type.
76   --  The object can be converted to standard Ada types.
77   type Object is private;
78   type Object_Value is private;
79
80   --  The null object.
81   Null_Object : constant Object;
82
83   --  ------------------------------
84   --  Type definition
85   --  ------------------------------
86   --  The Object_Type describes a type.  It serves as a basis
87   --  for type conversion.
88   type Object_Type is limited interface;
89   type Object_Type_Access is not null access constant Object_Type'Class;
90
91   --  Get the type name
92   function Get_Name (Type_Def : Object_Type) return String is abstract;
93
94   --  Get the base data type.
95   function Get_Data_Type (Type_Def : Object_Type) return Data_Type is abstract;
96
97   --  Convert the value into a string.
98   function To_String (Type_Def : in Object_Type;
99                       Value    : in Object_Value) return String is abstract;
100
101   --  Convert the value into a wide string.
102   function To_Wide_Wide_String (Type_Def : in Object_Type;
103                                 Value    : in Object_Value) return Wide_Wide_String is abstract;
104
105   --  Convert the value into an integer.
106   function To_Long_Long (Type_Def : in Object_Type;
107                          Value    : in Object_Value) return Long_Long_Integer is abstract;
108
109   --  Convert the value into a float.
110   function To_Long_Float (Type_Def : in Object_Type;
111                           Value    : in Object_Value) return Long_Long_Float is abstract;
112
113   --  Convert the value into a boolean.
114   function To_Boolean (Type_Def : in Object_Type;
115                        Value    : in Object_Value) return Boolean is abstract;
116
117   --  Convert the value into a duration.
118   function To_Duration (Type_Def : in Object_Type;
119                         Value    : in Object_Value) return Duration is abstract;
120
121   --  Returns True if the value is empty.
122   function Is_Empty (Type_Def : in Object_Type;
123                      Value    : in Object_Value) return Boolean is abstract;
124
125   --  ------------------------------
126   --  Generic Object holding a value
127   --  ------------------------------
128
129   --  Check whether the object contains a value.
130   --  Returns true if the object does not contain a value.
131   function Is_Null (Value : in Object) return Boolean;
132
133   --  Check whether the object is empty.
134   --  If the object is null, returns true.
135   --  If the object is the empty string, returns true.
136   --  If the object is a list bean whose Get_Count is 0, returns true.
137   --  Otherwise returns false.
138   function Is_Empty (Value : in Object) return Boolean;
139
140--     function Is_Constant (Value : in Object) return Boolean;
141   --  Get a type identification for the object value.
142   function Get_Type (Value : in Object) return Data_Type;
143
144   --  Get the type definition of the object value.
145   function Get_Type (Value : in Object) return Object_Type_Access;
146
147   --  Get the type name of this object.
148   function Get_Type_Name (Value : Object) return String;
149
150   --  Get the value identified by the name in the bean object.
151   --  If the value object is not a bean, returns the null object.
152   function Get_Value (Value : in Object;
153                       Name  : in String) return Object;
154
155   --  Convert the object to the corresponding type.
156   function To_String (Value : in Object) return String;
157   function To_Wide_Wide_String (Value : in Object) return Wide_Wide_String;
158   function To_Unbounded_String (Value : in Object) return Unbounded_String;
159   function To_Unbounded_Wide_Wide_String (Value : in Object) return Unbounded_Wide_Wide_String;
160   function To_Integer (Value : in Object) return Integer;
161   function To_Boolean (Value : in Object) return Boolean;
162   function To_Long_Integer (Value : in Object) return Long_Integer;
163   function To_Long_Long_Integer (Value : in Object) return Long_Long_Integer;
164   function To_Float (Value : in Object) return Float;
165   function To_Long_Float (Value : in Object) return Long_Float;
166   function To_Long_Long_Float (Value : in Object) return Long_Long_Float;
167   function To_Duration (Value : in Object) return Duration;
168
169   function To_Bean (Value : in Object) return access Util.Beans.Basic.Readonly_Bean'Class;
170
171   --  Convert the object to an object of another time.
172   --  Force the object to be an integer.
173   function Cast_Integer (Value : Object) return Object;
174
175   --  Force the object to be a float.
176   function Cast_Float (Value : Object) return Object;
177
178   --  Force the object to be a duration.
179   function Cast_Duration (Value : Object) return Object;
180
181   --  Force the object to be a string.
182   function Cast_String (Value : Object) return Object;
183
184   --  Convert a value to a generic typed object.
185   function To_Object (Value : in Integer) return Object;
186   function To_Object (Value : in Long_Integer) return Object;
187   function To_Object (Value : in Long_Long_Integer) return Object;
188   function To_Object (Value : in Float) return Object;
189   function To_Object (Value : in Long_Float) return Object;
190   function To_Object (Value : in Long_Long_Float) return Object;
191   function To_Object (Value : in String) return Object;
192   function To_Object (Value : in Wide_Wide_String) return Object;
193   function To_Object (Value : in Unbounded_String) return Object;
194   function To_Object (Value : in Unbounded_Wide_Wide_String) return Object;
195   function To_Object (Value : in Boolean) return Object;
196   function To_Object (Value : in Duration) return Object;
197
198   --  Create an object that refers to the bean object.  With the storage type
199   --  <b>DYNAMIC</b>, the default, the bean object will be freed when there is
200   --  no <b>Object</b> that refers to that bean.  With <b>STATIC</b>, the bean
201   --  is a static bean and it will not be freed automaticaly.
202   function To_Object (Value   : access Util.Beans.Basic.Readonly_Bean'Class;
203                       Storage : in Storage_Type := DYNAMIC) return Object;
204
205   --  Comparison of objects
206   function "<" (Left, Right : Object) return Boolean;
207   function "<=" (Left, Right : Object) return Boolean;
208   function ">" (Left, Right : Object) return Boolean;
209   function ">=" (Left, Right : Object) return Boolean;
210   function "=" (Left, Right : Object) return Boolean;
211
212   --  Arithmetic operations on objects
213   function "+" (Left, Right : Object) return Object;
214   function "-" (Left, Right : Object) return Object;
215   function "*" (Left, Right : Object) return Object;
216   function "/" (Left, Right : Object) return Object;
217   function "&" (Left, Right : Object) return Object;
218   function "mod" (Left, Right : Object) return Object;
219   function "-" (Left : Object) return Object;
220
221private
222
223   use Ada.Finalization;
224
225   type Name_Access is access constant String;
226
227   type Basic_Type is abstract limited new Object_Type with null record;
228
229   --  Convert the value into a wide string.
230   function To_Wide_Wide_String (Type_Def : in Basic_Type;
231                                 Value    : in Object_Value) return Wide_Wide_String;
232
233   --  Convert the value into an integer.
234   function To_Long_Long (Type_Def : in Basic_Type;
235                          Value    : in Object_Value) return Long_Long_Integer;
236
237   --  Convert the value into a float.
238   function To_Long_Float (Type_Def : in Basic_Type;
239                           Value    : in Object_Value) return Long_Long_Float;
240
241   --  Convert the value into a boolean.
242   function To_Boolean (Type_Def : in Basic_Type;
243                        Value    : in Object_Value) return Boolean;
244
245   --  Convert the value into a duration.
246   function To_Duration (Type_Def : in Basic_Type;
247                         Value    : in Object_Value) return Duration;
248
249   --  Returns False
250   function Is_Empty (Type_Def : in Basic_Type;
251                      Value    : in Object_Value) return Boolean;
252
253   --  ------------------------------
254   --  Null Type
255   --  ------------------------------
256   type Null_Type is new Basic_Type with null record;
257
258   --  Get the type name
259   function Get_Name (Type_Def : Null_Type) return String;
260
261   --  Get the base data type.
262   function Get_Data_Type (Type_Def : Null_Type) return Data_Type;
263
264   --  Convert the value into a string.
265   function To_String (Type_Def : in Null_Type;
266                       Value    : in Object_Value) return String;
267
268   --  Returns True
269   function Is_Empty (Type_Def : in Null_Type;
270                      Value    : in Object_Value) return Boolean;
271
272   --  ------------------------------
273   --  Integer Type
274   --  ------------------------------
275   type Int_Type is new Basic_Type with null record;
276
277   --  Get the type name
278   function Get_Name (Type_Def : Int_Type) return String;
279
280   --  Get the base data type.
281   function Get_Data_Type (Type_Def : Int_Type) return Data_Type;
282
283   function To_String (Type_Def : in Int_Type;
284                       Value    : in Object_Value) return String;
285
286   --  Convert the value into an integer.
287   function To_Long_Long (Type_Def : in Int_Type;
288                          Value    : in Object_Value) return Long_Long_Integer;
289
290   --  Convert the value into a float.
291   function To_Long_Float (Type_Def : in Int_Type;
292                           Value    : in Object_Value) return Long_Long_Float;
293
294   --  Convert the value into a boolean.
295   function To_Boolean (Type_Def : in Int_Type;
296                        Value    : in Object_Value) return Boolean;
297
298   --  Convert the value into a duration.
299   function To_Duration (Type_Def : in Int_Type;
300                         Value    : in Object_Value) return Duration;
301
302   --  ------------------------------
303   --  Float Type
304   --  ------------------------------
305   type Float_Type is new Basic_Type with null record;
306
307   --  Get the type name
308   function Get_Name (Type_Def : in Float_Type) return String;
309
310   --  Get the base data type.
311   function Get_Data_Type (Type_Def : in Float_Type) return Data_Type;
312
313   --  Convert the value into a string.
314   function To_String (Type_Def : in Float_Type;
315                       Value    : in Object_Value) return String;
316
317   --  Convert the value into an integer.
318   function To_Long_Long (Type_Def : in Float_Type;
319                          Value    : in Object_Value) return Long_Long_Integer;
320
321   --  Convert the value into a float.
322   function To_Long_Float (Type_Def : in Float_Type;
323                           Value    : in Object_Value) return Long_Long_Float;
324
325   --  Convert the value into a boolean.
326   function To_Boolean (Type_Def : in Float_Type;
327                        Value    : in Object_Value) return Boolean;
328
329   --  Convert the value into a duration.
330   function To_Duration (Type_Def : in Float_Type;
331                         Value    : in Object_Value) return Duration;
332
333   --  ------------------------------
334   --  String Type
335   --  ------------------------------
336   type String_Type is new Basic_Type with null record;
337
338   --  Get the type name
339   function Get_Name (Type_Def : in String_Type) return String;
340
341   --  Get the base data type.
342   function Get_Data_Type (Type_Def : in String_Type) return Data_Type;
343
344   --  Convert the value into a string.
345   function To_String (Type_Def : in String_Type;
346                       Value    : in Object_Value) return String;
347
348   --  Convert the value into an integer.
349   function To_Long_Long (Type_Def : in String_Type;
350                          Value    : in Object_Value) return Long_Long_Integer;
351
352   --  Convert the value into a float.
353   function To_Long_Float (Type_Def : in String_Type;
354                           Value    : in Object_Value) return Long_Long_Float;
355
356   --  Convert the value into a boolean.
357   function To_Boolean (Type_Def : in String_Type;
358                        Value    : in Object_Value) return Boolean;
359
360   --  Convert the value into a duration.
361   function To_Duration (Type_Def : in String_Type;
362                         Value    : in Object_Value) return Duration;
363
364   --  Returns True if the value is empty.
365   function Is_Empty (Type_Def : in String_Type;
366                      Value    : in Object_Value) return Boolean;
367
368   --  ------------------------------
369   --  Wide String Type
370   --  ------------------------------
371   type Wide_String_Type is new Basic_Type with null record;
372
373   --  Get the type name
374   function Get_Name (Type_Def : in Wide_String_Type) return String;
375
376   --  Get the base data type.
377   function Get_Data_Type (Type_Def : in Wide_String_Type) return Data_Type;
378
379   --  Convert the value into a string.
380   function To_String (Type_Def : in Wide_String_Type;
381                       Value    : in Object_Value) return String;
382
383   --  Convert the value into a wide string.
384   function To_Wide_Wide_String (Type_Def : in Wide_String_Type;
385                                 Value    : in Object_Value) return Wide_Wide_String;
386
387   --  Convert the value into an integer.
388   function To_Long_Long (Type_Def : in Wide_String_Type;
389                          Value    : in Object_Value) return Long_Long_Integer;
390
391   --  Convert the value into a float.
392   function To_Long_Float (Type_Def : in Wide_String_Type;
393                           Value    : in Object_Value) return Long_Long_Float;
394
395   --  Convert the value into a boolean.
396   function To_Boolean (Type_Def : in Wide_String_Type;
397                        Value    : in Object_Value) return Boolean;
398
399   --  Convert the value into a duration.
400   function To_Duration (Type_Def : in Wide_String_Type;
401                         Value    : in Object_Value) return Duration;
402
403   --  Returns True if the value is empty.
404   function Is_Empty (Type_Def : in Wide_String_Type;
405                      Value    : in Object_Value) return Boolean;
406
407   --  ------------------------------
408   --  Boolean Type
409   --  ------------------------------
410   type Boolean_Type is new Basic_Type with null record;
411
412   --  Get the type name
413   function Get_Name (Type_Def : in Boolean_Type) return String;
414
415   --  Get the base data type.
416   function Get_Data_Type (Type_Def : in Boolean_Type) return Data_Type;
417
418   --  Convert the value into a string.
419   function To_String (Type_Def : in Boolean_Type;
420                       Value    : in Object_Value) return String;
421
422   --  Convert the value into an integer.
423   function To_Long_Long (Type_Def : in Boolean_Type;
424                          Value    : in Object_Value) return Long_Long_Integer;
425
426   --  Convert the value into a float.
427   function To_Long_Float (Type_Def : in Boolean_Type;
428                           Value    : in Object_Value) return Long_Long_Float;
429
430   --  Convert the value into a boolean.
431   function To_Boolean (Type_Def : in Boolean_Type;
432                        Value    : in Object_Value) return Boolean;
433
434   --  ------------------------------
435   --  Duration Type
436   --  ------------------------------
437   type Duration_Type_Def is new Basic_Type with null record;
438
439   --  Get the type name
440   function Get_Name (Type_Def : in Duration_Type_Def) return String;
441
442   --  Get the base data type.
443   function Get_Data_Type (Type_Def : in Duration_Type_Def) return Data_Type;
444
445   --  Convert the value into a string.
446   function To_String (Type_Def : in Duration_Type_Def;
447                       Value    : in Object_Value) return String;
448
449   --  Convert the value into an integer.
450   function To_Long_Long (Type_Def : in Duration_Type_Def;
451                          Value    : in Object_Value) return Long_Long_Integer;
452
453   --  Convert the value into a float.
454   function To_Long_Float (Type_Def : in Duration_Type_Def;
455                           Value    : in Object_Value) return Long_Long_Float;
456
457   --  Convert the value into a boolean.
458   function To_Boolean (Type_Def : in Duration_Type_Def;
459                        Value    : in Object_Value) return Boolean;
460
461   --  Convert the value into a duration.
462   function To_Duration (Type_Def : in Duration_Type_Def;
463                         Value    : in Object_Value) return Duration;
464
465   --  ------------------------------
466   --  Bean Type
467   --  ------------------------------
468   type Bean_Type is new Basic_Type with null record;
469
470   --  Get the type name
471   function Get_Name (Type_Def : in Bean_Type) return String;
472
473   --  Get the base data type.
474   function Get_Data_Type (Type_Def : in Bean_Type) return Data_Type;
475
476   --  Convert the value into a string.
477   function To_String (Type_Def : in Bean_Type;
478                       Value    : in Object_Value) return String;
479
480   --  Convert the value into an integer.
481   function To_Long_Long (Type_Def : in Bean_Type;
482                          Value    : in Object_Value) return Long_Long_Integer;
483
484   --  Convert the value into a float.
485   function To_Long_Float (Type_Def : in Bean_Type;
486                           Value    : in Object_Value) return Long_Long_Float;
487
488   --  Convert the value into a boolean.
489   function To_Boolean (Type_Def : in Bean_Type;
490                        Value    : in Object_Value) return Boolean;
491
492   --  Returns True if the value is empty.
493   function Is_Empty (Type_Def : in Bean_Type;
494                      Value    : in Object_Value) return Boolean;
495
496   subtype Proxy_Data_Type is Data_Type range TYPE_STRING .. TYPE_BEAN;
497
498   type Proxy is tagged limited record
499      Ref_Counter : Util.Concurrent.Counters.Counter;
500   end record;
501
502   --  Release the object pointed to by the proxy (if necessary).
503   procedure Release (P : in out Proxy) is null;
504
505   type Bean_Proxy_Access is access all Proxy'Class;
506
507   type String_Proxy (Len : Natural) is new Proxy with record
508      Value : String (1 .. Len);
509   end record;
510   type String_Proxy_Access is access all String_Proxy;
511
512   type Wide_String_Proxy (Len : Natural) is new Proxy with record
513      Value : Wide_Wide_String (1 .. Len);
514   end record;
515   type Wide_String_Proxy_Access is access all Wide_String_Proxy;
516
517   type Bean_Proxy is new Proxy with record
518      Bean    : access Util.Beans.Basic.Readonly_Bean'Class;
519      Storage : Storage_Type;
520   end record;
521
522   --  Release the object pointed to by the proxy (if necessary).
523   overriding
524   procedure Release (P : in out Bean_Proxy);
525
526   type Object_Value (Of_Type : Data_Type := TYPE_NULL) is record
527      case Of_Type is
528         when TYPE_NULL =>
529            null;
530
531            --  Integers and enums are stored as 64-bit integer.
532         when TYPE_INTEGER =>
533            Int_Value : Long_Long_Integer;
534
535         when TYPE_BOOLEAN =>
536            Bool_Value : Boolean;
537
538         when TYPE_FLOAT =>
539            Float_Value : Long_Long_Float;
540
541         when TYPE_TIME =>
542            Time_Value  : Duration;
543
544         when TYPE_STRING =>
545            String_Proxy : String_Proxy_Access;
546
547         when TYPE_WIDE_STRING =>
548            Wide_Proxy : Wide_String_Proxy_Access;
549
550         when TYPE_BEAN =>
551            Proxy : Bean_Proxy_Access;
552
553      end case;
554   end record;
555
556   No_Type     : aliased constant Null_Type := Null_Type '(others => <>);
557
558   Null_Value  : constant Object_Value := Object_Value '(Of_Type => TYPE_NULL);
559
560   type Object is new Controlled with record
561      Type_Def : Object_Type_Access := No_Type'Access;
562      V        : Object_Value := Null_Value;
563   end record;
564
565   overriding
566   procedure Adjust (Obj : in out Object);
567
568   overriding
569   procedure Finalize (Obj : in out Object);
570
571   Null_Object : constant Object := Object '(Controlled with
572                                             V        => Object_Value '(Of_Type => TYPE_NULL),
573                                             Type_Def => No_Type'Access);
574
575end Util.Beans.Objects;
576