1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Copyright 2014 Alexis Laferrière <alexis.laf@xymus.net>
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
9 # http://www.apache.org/licenses/LICENSE-2.0
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
17 # Abstract services to serialize Nit objects to different formats
19 # This module declares the `serialize` annotation to mark Nit classes as serializable.
20 # For an introduction to this service, refer to the documentation of the `serialization` group.
21 # This documentation provides more technical information on interesting entitie of this module.
23 # Interesting entities for end users of serializable classes:
25 # * Serialize an instance subclass of `Serializable` with either
26 # `Serializer::serializable` and `Serializable::serialize`.
27 # * Deserialize an object using `Deserializer::deserialize`.
28 # The object type must the be checked with an `assert` or otherwise.
30 # Interesting entities to create custom serializable classes:
32 # * Subclass `Serializable` to declare a class as serializable and to customize
33 # the serialization and deserialization behavior.
34 # * Redefine `Serializable::core_serialize_to` to customize the serialization
35 # of the receiver class.
36 # * Redefine `Deserializer::deserialize_class` to customize the deserialization
37 # of a specific class by name.
39 # Interesting entities for serialization format:
41 # * Subclass `Serializer` and `Deserializer` with custom serices.
42 # * In `Serializer`, `serialize` and `serialize_reference` must be redefined.
43 # * In `Deserializer`; `deserialize`, `deserialize_attribute and
44 # `notify_of_creation` must be redefined.
45 module serialization
is
46 new_annotation auto_serializable
47 new_annotation serialize
48 new_annotation noserialize
51 # Abstract serialization service to be sub-classed by specialized services.
53 # Entry point method of this service, serialize the `object`
55 # This method, and refinements, should handle `null` and probably
56 # use double dispatch to customize the bahavior per serializable objects.
57 fun serialize
(object
: nullable Serializable) is abstract
59 # Serialize an object, with full serialization or a simple reference
60 protected fun serialize_reference
(object
: Serializable) is abstract
62 # Serialize an attribute to compose a serializable object
64 # This method should be called from `Serializable::core_serialize_to`.
65 fun serialize_attribute
(name
: String, value
: nullable Object)
67 if not try_to_serialize
(value
) then
68 warn
("argument {name} of type {value.class_name} is not serializable.")
72 # Serialize `value` is possie, i.e. it is `Serializable` or `null`
73 fun try_to_serialize
(value
: nullable Object): Bool
75 if value
isa Serializable then
76 value
.serialize_to_or_delay
(self)
77 else if value
== null then
83 # Warn of problems and potential errors (such as if an attribute
84 # is not serializable)
85 fun warn
(msg
: String) do print
"Serialization warning: {msg}"
88 # Abstract deserialization service
90 # After initialization of one of its sub-classes, call `deserialize`
91 interface Deserializer
92 # Main method of this class, returns a Nit object
93 fun deserialize
: nullable Object is abstract
95 # Internal method to be implemented by sub-classes
96 fun deserialize_attribute
(name
: String): nullable Object is abstract
98 # Internal method called by objects in creation,
99 # to be implemented by sub-classes
100 fun notify_of_creation
(new_object
: Object) is abstract
102 # Deserialize the next available object as an instance of `class_name`
104 # Returns the deserialized object on success, aborts on error.
106 # This method should be redefined for each custom subclass of `Serializable`.
107 # All refinement should look for a precise `class_name` and call super
108 # on unsupported classes.
109 fun deserialize_class
(class_name
: String): Object do
110 print
"Error: doesn't know how to deserialize class \"{class_name}\
""
115 # Instances of this class can be passed to `Serializer::serialize`
116 interface Serializable
117 # Serialize `self` to `serializer`
119 # This is a shortcut to `Serializer::serialize`.
120 fun serialize_to
(serializer
: Serializer) do serializer
.serialize
(self)
122 # Actual serialization of `self` to `serializer`
124 # This writes the full data of `self` to `serializer`.
126 # This method can be redefined in sub classes and refinements.
127 # It should use `Serializer::serialize_attribute` to to register real or
128 # logical attributes.
130 # Any refinement should have its equivalent refinement of
131 # `Deserializer::deserialize_class` to support this custom deserialization.
132 fun core_serialize_to
(serializer
: Serializer) do end
134 # Accept references or force direct serialization (using `serialize_to`)
136 # The subclass change the default behavior, which will accept references,
137 # to force to always serialize copies of `self`.
138 private fun serialize_to_or_delay
(v
: Serializer) do v
.serialize_reference
(self)
140 # Create an instance of this class from the `deserializer`
142 # This constructor is refined by subclasses to correctly build their instances.
143 init from_deserializer
(deserializer
: Deserializer) do end
146 redef interface Object
147 # Is `self` the same as `other` in a serialization context?
149 # Used to determine if an object has already been serialized.
150 fun is_same_serialized
(other
: nullable Object): Bool do return is_same_instance
(other
)
152 # Hash value use for serialization
154 # Used in combination with `is_same_serialized`. If two objects are the same
155 # in a serialization context, they must have the same `serialization_hash`.
156 fun serialization_hash
: Int do return object_id
159 # Instances of this class are not delayed and instead serialized immediately
160 # This applies mainly to `universal` types
161 interface DirectSerializable
164 redef fun serialize_to_or_delay
(v
) do serialize_to
(v
)
167 redef class Bool super DirectSerializable end
168 redef class Char super DirectSerializable end
169 redef class Int super DirectSerializable end
170 redef class Float super DirectSerializable end
171 redef class NativeString super DirectSerializable end
172 redef class String super DirectSerializable end
173 redef class SimpleCollection[E
] super Serializable end
174 redef class Map[K
, V
] super Serializable end
176 redef class Couple[F
, S
]
179 redef init from_deserializer
(v
)
181 v
.notify_of_creation
self
182 var first
= v
.deserialize_attribute
("first")
183 var second
= v
.deserialize_attribute
("second")
187 redef fun core_serialize_to
(v
)
189 v
.serialize_attribute
("first", first
)
190 v
.serialize_attribute
("second", second
)
194 redef class Container[E
]
197 redef init from_deserializer
(v
)
199 v
.notify_of_creation
self
200 var item
= v
.deserialize_attribute
("item")
204 redef fun core_serialize_to
(v
)
206 v
.serialize_attribute
("item", first
)